github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/cf/api/curl_test.go (about) 1 package api_test 2 3 import ( 4 "net/http" 5 "net/http/httptest" 6 "strings" 7 "time" 8 9 "code.cloudfoundry.org/cli/cf/api/apifakes" 10 "code.cloudfoundry.org/cli/cf/configuration/coreconfig" 11 "code.cloudfoundry.org/cli/cf/net" 12 "code.cloudfoundry.org/cli/cf/terminal/terminalfakes" 13 testconfig "code.cloudfoundry.org/cli/cf/util/testhelpers/configuration" 14 testnet "code.cloudfoundry.org/cli/cf/util/testhelpers/net" 15 16 . "code.cloudfoundry.org/cli/cf/api" 17 "code.cloudfoundry.org/cli/cf/trace/tracefakes" 18 . "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers" 19 . "github.com/onsi/ginkgo" 20 . "github.com/onsi/gomega" 21 "github.com/onsi/gomega/ghttp" 22 ) 23 24 var _ = Describe("CloudControllerCurlRepository ", func() { 25 var ( 26 headers string 27 body string 28 apiErr error 29 ) 30 31 Describe("GET requests", func() { 32 BeforeEach(func() { 33 req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 34 Method: "GET", 35 Path: "/v2/endpoint", 36 Response: testnet.TestResponse{ 37 Status: http.StatusOK, 38 Body: expectedJSONResponse}, 39 }) 40 ts, handler := testnet.NewServer([]testnet.TestRequest{req}) 41 defer ts.Close() 42 43 deps := newCurlDependencies() 44 deps.config.SetAPIEndpoint(ts.URL) 45 46 repo := NewCloudControllerCurlRepository(deps.config, deps.gateway) 47 headers, body, apiErr = repo.Request("GET", "/v2/endpoint", "", "", false) 48 49 Expect(handler).To(HaveAllRequestsCalled()) 50 Expect(apiErr).NotTo(HaveOccurred()) 51 }) 52 53 It("returns headers with the status code", func() { 54 Expect(headers).To(ContainSubstring("200")) 55 }) 56 57 It("returns the header content type", func() { 58 Expect(headers).To(ContainSubstring("Content-Type")) 59 Expect(headers).To(ContainSubstring("text/plain")) 60 }) 61 62 It("returns the body as a JSON-encoded string", func() { 63 Expect(removeWhitespace(body)).To(Equal(removeWhitespace(expectedJSONResponse))) 64 }) 65 }) 66 67 Describe("POST requests", func() { 68 BeforeEach(func() { 69 req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 70 Method: "POST", 71 Path: "/v2/endpoint", 72 Matcher: testnet.RequestBodyMatcher(`{"key":"val"}`), 73 Response: testnet.TestResponse{ 74 Status: http.StatusOK, 75 Body: expectedJSONResponse}, 76 }) 77 78 ts, handler := testnet.NewServer([]testnet.TestRequest{req}) 79 defer ts.Close() 80 81 deps := newCurlDependencies() 82 deps.config.SetAPIEndpoint(ts.URL) 83 84 repo := NewCloudControllerCurlRepository(deps.config, deps.gateway) 85 headers, body, apiErr = repo.Request("POST", "/v2/endpoint", "", `{"key":"val"}`, false) 86 Expect(handler).To(HaveAllRequestsCalled()) 87 }) 88 89 It("does not return an error", func() { 90 Expect(apiErr).NotTo(HaveOccurred()) 91 }) 92 93 Context("when the server returns a 400 Bad Request header", func() { 94 var ( 95 deps curlDependencies 96 handler *testnet.TestHandler 97 ts *httptest.Server 98 failOnHTTPError bool 99 ) 100 101 BeforeEach(func() { 102 req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 103 Method: "POST", 104 Path: "/v2/endpoint", 105 Matcher: testnet.RequestBodyMatcher(`{"key":"val"}`), 106 Response: testnet.TestResponse{ 107 Status: http.StatusBadRequest, 108 Body: expectedJSONResponse}, 109 }) 110 111 ts, handler = testnet.NewServer([]testnet.TestRequest{req}) 112 113 deps = newCurlDependencies() 114 deps.config.SetAPIEndpoint(ts.URL) 115 failOnHTTPError = false 116 }) 117 118 AfterEach(func() { 119 ts.Close() 120 }) 121 122 JustBeforeEach(func() { 123 repo := NewCloudControllerCurlRepository(deps.config, deps.gateway) 124 _, body, apiErr = repo.Request("POST", "/v2/endpoint", "", `{"key":"val"}`, failOnHTTPError) 125 Expect(handler).To(HaveAllRequestsCalled()) 126 }) 127 128 It("returns the response body", func() { 129 Expect(removeWhitespace(body)).To(Equal(removeWhitespace(expectedJSONResponse))) 130 }) 131 132 It("does not return an error", func() { 133 Expect(apiErr).NotTo(HaveOccurred()) 134 }) 135 136 When("the failOnHttpError is true", func() { 137 BeforeEach(func() { 138 failOnHTTPError = true 139 }) 140 141 It("returns the error", func() { 142 Expect(apiErr).To(HaveOccurred()) 143 }) 144 }) 145 }) 146 147 Context("when provided with invalid headers", func() { 148 It("returns an error", func() { 149 deps := newCurlDependencies() 150 repo := NewCloudControllerCurlRepository(deps.config, deps.gateway) 151 _, _, apiErr := repo.Request("POST", "/v2/endpoint", "not-valid", "", false) 152 Expect(apiErr).To(HaveOccurred()) 153 Expect(apiErr.Error()).To(ContainSubstring("headers")) 154 }) 155 }) 156 157 Context("when provided with valid headers", func() { 158 It("sends them along with the POST body", func() { 159 req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 160 Method: "POST", 161 Path: "/v2/endpoint", 162 Matcher: func(req *http.Request) { 163 Expect(req.Header.Get("content-type")).To(Equal("ascii/cats")) 164 Expect(req.Header.Get("x-something-else")).To(Equal("5")) 165 }, 166 Response: testnet.TestResponse{ 167 Status: http.StatusOK, 168 Body: expectedJSONResponse}, 169 }) 170 ts, handler := testnet.NewServer([]testnet.TestRequest{req}) 171 defer ts.Close() 172 173 deps := newCurlDependencies() 174 deps.config.SetAPIEndpoint(ts.URL) 175 176 headers := "content-type: ascii/cats\nx-something-else:5" 177 repo := NewCloudControllerCurlRepository(deps.config, deps.gateway) 178 _, _, apiErr := repo.Request("POST", "/v2/endpoint", headers, "", false) 179 Expect(handler).To(HaveAllRequestsCalled()) 180 Expect(apiErr).NotTo(HaveOccurred()) 181 }) 182 }) 183 }) 184 185 It("uses POST as the default method when a body is provided", func() { 186 ccServer := ghttp.NewServer() 187 ccServer.AppendHandlers( 188 ghttp.VerifyRequest("POST", "/v2/endpoint"), 189 ) 190 191 deps := newCurlDependencies() 192 deps.config.SetAPIEndpoint(ccServer.URL()) 193 194 repo := NewCloudControllerCurlRepository(deps.config, deps.gateway) 195 _, _, err := repo.Request("", "/v2/endpoint", "", "body", false) 196 Expect(err).NotTo(HaveOccurred()) 197 198 Expect(ccServer.ReceivedRequests()).To(HaveLen(1)) 199 }) 200 201 It("uses GET as the default method when a body is not provided", func() { 202 ccServer := ghttp.NewServer() 203 ccServer.AppendHandlers( 204 ghttp.VerifyRequest("GET", "/v2/endpoint"), 205 ) 206 207 deps := newCurlDependencies() 208 deps.config.SetAPIEndpoint(ccServer.URL()) 209 210 repo := NewCloudControllerCurlRepository(deps.config, deps.gateway) 211 _, _, err := repo.Request("", "/v2/endpoint", "", "", false) 212 Expect(err).NotTo(HaveOccurred()) 213 214 Expect(ccServer.ReceivedRequests()).To(HaveLen(1)) 215 }) 216 }) 217 218 const expectedJSONResponse = ` 219 {"resources": [ 220 { 221 "metadata": { "guid": "my-quota-guid" }, 222 "entity": { "name": "my-remote-quota", "memory_limit": 1024 } 223 } 224 ]} 225 ` 226 227 type curlDependencies struct { 228 config coreconfig.ReadWriter 229 gateway net.Gateway 230 } 231 232 func newCurlDependencies() (deps curlDependencies) { 233 deps.config = testconfig.NewRepository() 234 deps.config.SetAccessToken("BEARER my_access_token") 235 deps.gateway = net.NewCloudControllerGateway(deps.config, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "") 236 return 237 } 238 239 func removeWhitespace(body string) string { 240 body = strings.Replace(body, " ", "", -1) 241 body = strings.Replace(body, "\n", "", -1) 242 body = strings.Replace(body, "\r", "", -1) 243 body = strings.Replace(body, "\t", "", -1) 244 return body 245 }