github.com/xzl8028/xenia-server@v0.0.0-20190809101854-18450a97da63/services/imageproxy/local_test.go (about)

     1  // Copyright (c) 2017-present Xenia, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package imageproxy
     5  
     6  import (
     7  	"io/ioutil"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/xzl8028/xenia-server/model"
    14  	"github.com/xzl8028/xenia-server/services/httpservice"
    15  	"github.com/xzl8028/xenia-server/utils/testutils"
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  func makeTestLocalProxy() *ImageProxy {
    21  	configService := &testutils.StaticConfigService{
    22  		Cfg: &model.Config{
    23  			ServiceSettings: model.ServiceSettings{
    24  				SiteURL:                             model.NewString("https://xenia.example.com"),
    25  				AllowedUntrustedInternalConnections: model.NewString("127.0.0.1"),
    26  			},
    27  			ImageProxySettings: model.ImageProxySettings{
    28  				Enable:         model.NewBool(true),
    29  				ImageProxyType: model.NewString(model.IMAGE_PROXY_TYPE_LOCAL),
    30  			},
    31  		},
    32  	}
    33  
    34  	return MakeImageProxy(configService, httpservice.MakeHTTPService(configService), nil)
    35  }
    36  
    37  func TestLocalBackend_GetImage(t *testing.T) {
    38  	t.Run("image", func(t *testing.T) {
    39  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    40  			w.Header().Set("Cache-Control", "max-age=2592000, private")
    41  			w.Header().Set("Content-Type", "image/png")
    42  			w.Header().Set("Content-Length", "10")
    43  
    44  			w.WriteHeader(http.StatusOK)
    45  			w.Write([]byte("1111111111"))
    46  		})
    47  
    48  		mock := httptest.NewServer(handler)
    49  		defer mock.Close()
    50  
    51  		proxy := makeTestLocalProxy()
    52  
    53  		recorder := httptest.NewRecorder()
    54  		request, _ := http.NewRequest(http.MethodGet, "", nil)
    55  		proxy.GetImage(recorder, request, mock.URL+"/image.png")
    56  		resp := recorder.Result()
    57  
    58  		require.Equal(t, http.StatusOK, resp.StatusCode)
    59  		assert.Equal(t, "max-age=2592000, private", resp.Header.Get("Cache-Control"))
    60  		assert.Equal(t, "10", resp.Header.Get("Content-Length"))
    61  
    62  		respBody, _ := ioutil.ReadAll(resp.Body)
    63  		assert.Equal(t, []byte("1111111111"), respBody)
    64  	})
    65  
    66  	t.Run("not an image", func(t *testing.T) {
    67  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    68  			w.WriteHeader(http.StatusNotAcceptable)
    69  		})
    70  
    71  		mock := httptest.NewServer(handler)
    72  		defer mock.Close()
    73  
    74  		proxy := makeTestLocalProxy()
    75  
    76  		recorder := httptest.NewRecorder()
    77  		request, _ := http.NewRequest(http.MethodGet, "", nil)
    78  		proxy.GetImage(recorder, request, mock.URL+"/file.pdf")
    79  		resp := recorder.Result()
    80  
    81  		require.Equal(t, http.StatusNotAcceptable, resp.StatusCode)
    82  	})
    83  
    84  	t.Run("not an image, but remote server ignores accept header", func(t *testing.T) {
    85  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    86  			w.Header().Set("Cache-Control", "max-age=2592000, private")
    87  			w.Header().Set("Content-Type", "application/pdf")
    88  			w.Header().Set("Content-Length", "10")
    89  
    90  			w.WriteHeader(http.StatusOK)
    91  			w.Write([]byte("1111111111"))
    92  		})
    93  
    94  		mock := httptest.NewServer(handler)
    95  		defer mock.Close()
    96  
    97  		proxy := makeTestLocalProxy()
    98  
    99  		recorder := httptest.NewRecorder()
   100  		request, _ := http.NewRequest(http.MethodGet, "", nil)
   101  		proxy.GetImage(recorder, request, mock.URL+"/file.pdf")
   102  		resp := recorder.Result()
   103  
   104  		require.Equal(t, http.StatusForbidden, resp.StatusCode)
   105  	})
   106  
   107  	t.Run("not found", func(t *testing.T) {
   108  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   109  			w.WriteHeader(http.StatusNotFound)
   110  		})
   111  
   112  		mock := httptest.NewServer(handler)
   113  		defer mock.Close()
   114  
   115  		proxy := makeTestLocalProxy()
   116  
   117  		recorder := httptest.NewRecorder()
   118  		request, _ := http.NewRequest(http.MethodGet, "", nil)
   119  		proxy.GetImage(recorder, request, mock.URL+"/image.png")
   120  		resp := recorder.Result()
   121  
   122  		require.Equal(t, http.StatusNotFound, resp.StatusCode)
   123  	})
   124  
   125  	t.Run("other server error", func(t *testing.T) {
   126  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   127  			w.WriteHeader(http.StatusInternalServerError)
   128  		})
   129  
   130  		mock := httptest.NewServer(handler)
   131  		defer mock.Close()
   132  
   133  		proxy := makeTestLocalProxy()
   134  
   135  		recorder := httptest.NewRecorder()
   136  		request, _ := http.NewRequest(http.MethodGet, "", nil)
   137  		proxy.GetImage(recorder, request, mock.URL+"/image.png")
   138  		resp := recorder.Result()
   139  
   140  		require.Equal(t, http.StatusInternalServerError, resp.StatusCode)
   141  	})
   142  
   143  	t.Run("timeout", func(t *testing.T) {
   144  		wait := make(chan bool, 1)
   145  
   146  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   147  			<-wait
   148  		})
   149  
   150  		mock := httptest.NewServer(handler)
   151  		defer mock.Close()
   152  
   153  		proxy := makeTestLocalProxy()
   154  
   155  		// Modify the timeout to be much shorter than the default 30 seconds
   156  		proxy.backend.(*LocalBackend).impl.Timeout = time.Millisecond
   157  
   158  		recorder := httptest.NewRecorder()
   159  		request, _ := http.NewRequest(http.MethodGet, "", nil)
   160  		proxy.GetImage(recorder, request, mock.URL+"/image.png")
   161  		resp := recorder.Result()
   162  
   163  		require.Equal(t, http.StatusGatewayTimeout, resp.StatusCode)
   164  
   165  		wait <- true
   166  	})
   167  }
   168  
   169  func TestLocalBackend_GetImageDirect(t *testing.T) {
   170  	t.Run("image", func(t *testing.T) {
   171  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   172  			w.Header().Set("Cache-Control", "max-age=2592000, private")
   173  			w.Header().Set("Content-Type", "image/png")
   174  			w.Header().Set("Content-Length", "10")
   175  
   176  			w.WriteHeader(http.StatusOK)
   177  			w.Write([]byte("1111111111"))
   178  		})
   179  
   180  		mock := httptest.NewServer(handler)
   181  		defer mock.Close()
   182  
   183  		proxy := makeTestLocalProxy()
   184  
   185  		body, contentType, err := proxy.GetImageDirect(mock.URL + "/image.png")
   186  
   187  		assert.Nil(t, err)
   188  		assert.Equal(t, "image/png", contentType)
   189  
   190  		respBody, _ := ioutil.ReadAll(body)
   191  		assert.Equal(t, []byte("1111111111"), respBody)
   192  	})
   193  
   194  	t.Run("not an image", func(t *testing.T) {
   195  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   196  			w.WriteHeader(http.StatusNotAcceptable)
   197  		})
   198  
   199  		mock := httptest.NewServer(handler)
   200  		defer mock.Close()
   201  
   202  		proxy := makeTestLocalProxy()
   203  
   204  		body, contentType, err := proxy.GetImageDirect(mock.URL + "/file.pdf")
   205  
   206  		assert.NotNil(t, err)
   207  		assert.Equal(t, "", contentType)
   208  		assert.Equal(t, ErrLocalRequestFailed, err)
   209  		assert.Nil(t, body)
   210  	})
   211  
   212  	t.Run("not an image, but remote server ignores accept header", func(t *testing.T) {
   213  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   214  			w.Header().Set("Cache-Control", "max-age=2592000, private")
   215  			w.Header().Set("Content-Type", "application/pdf")
   216  			w.Header().Set("Content-Length", "10")
   217  
   218  			w.WriteHeader(http.StatusOK)
   219  			w.Write([]byte("1111111111"))
   220  		})
   221  
   222  		mock := httptest.NewServer(handler)
   223  		defer mock.Close()
   224  
   225  		proxy := makeTestLocalProxy()
   226  
   227  		body, contentType, err := proxy.GetImageDirect(mock.URL + "/file.pdf")
   228  
   229  		assert.NotNil(t, err)
   230  		assert.Equal(t, "", contentType)
   231  		assert.Equal(t, ErrLocalRequestFailed, err)
   232  		assert.Nil(t, body)
   233  	})
   234  
   235  	t.Run("not found", func(t *testing.T) {
   236  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   237  			w.WriteHeader(http.StatusNotFound)
   238  		})
   239  
   240  		mock := httptest.NewServer(handler)
   241  		defer mock.Close()
   242  
   243  		proxy := makeTestLocalProxy()
   244  
   245  		body, contentType, err := proxy.GetImageDirect(mock.URL + "/image.png")
   246  
   247  		assert.NotNil(t, err)
   248  		assert.Equal(t, "", contentType)
   249  		assert.Equal(t, ErrLocalRequestFailed, err)
   250  		assert.Nil(t, body)
   251  	})
   252  
   253  	t.Run("other server error", func(t *testing.T) {
   254  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   255  			w.WriteHeader(http.StatusInternalServerError)
   256  		})
   257  
   258  		mock := httptest.NewServer(handler)
   259  		defer mock.Close()
   260  
   261  		proxy := makeTestLocalProxy()
   262  
   263  		body, contentType, err := proxy.GetImageDirect(mock.URL + "/image.png")
   264  
   265  		assert.NotNil(t, err)
   266  		assert.Equal(t, "", contentType)
   267  		assert.Equal(t, ErrLocalRequestFailed, err)
   268  		assert.Nil(t, body)
   269  	})
   270  
   271  	t.Run("timeout", func(t *testing.T) {
   272  		wait := make(chan bool, 1)
   273  
   274  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   275  			<-wait
   276  		})
   277  
   278  		mock := httptest.NewServer(handler)
   279  		defer mock.Close()
   280  
   281  		proxy := makeTestLocalProxy()
   282  
   283  		// Modify the timeout to be much shorter than the default 30 seconds
   284  		proxy.backend.(*LocalBackend).impl.Timeout = time.Millisecond
   285  
   286  		body, contentType, err := proxy.GetImageDirect(mock.URL + "/image.png")
   287  
   288  		assert.NotNil(t, err)
   289  		assert.Equal(t, "", contentType)
   290  		assert.Equal(t, ErrLocalRequestFailed, err)
   291  		assert.Nil(t, body)
   292  
   293  		wait <- true
   294  	})
   295  }