github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/resty/request_test.go (about) 1 // Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com), All rights reserved. 2 // resty source code and usage is governed by a MIT style 3 // license that can be found in the LICENSE file. 4 5 package resty 6 7 import ( 8 "bytes" 9 "crypto/tls" 10 "encoding/xml" 11 "errors" 12 "io" 13 "net" 14 "net/http" 15 "net/url" 16 "os" 17 "path/filepath" 18 "strconv" 19 "strings" 20 "testing" 21 "time" 22 23 "github.com/bingoohuang/gg/pkg/iox" 24 "github.com/stretchr/testify/assert" 25 ) 26 27 type AuthSuccess struct { 28 ID, Message string 29 } 30 31 type AuthError struct { 32 ID, Message string 33 } 34 35 func TestGet(t *testing.T) { 36 ts := createGetServer(t) 37 defer ts.Close() 38 39 resp, err := dc().R(). 40 SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)). 41 Get(ts.URL + "/") 42 43 assert.Nil(t, err) 44 assert.Equal(t, http.StatusOK, resp.StatusCode()) 45 assert.Equal(t, "HTTP/1.1", resp.Proto()) 46 assert.Equal(t, "200 OK", resp.Status()) 47 assert.NotNil(t, resp.Body()) 48 assert.Equal(t, "TestGet: text response", resp.String()) 49 50 logResponse(t, resp) 51 } 52 53 func TestIllegalRetryCount(t *testing.T) { 54 ts := createGetServer(t) 55 defer ts.Close() 56 57 resp, err := dc().SetRetryCount(-1).R().Get(ts.URL + "/") 58 59 assert.Nil(t, err) 60 assert.Nil(t, resp) 61 } 62 63 func TestGetCustomUserAgent(t *testing.T) { 64 ts := createGetServer(t) 65 defer ts.Close() 66 67 resp, err := dcr(). 68 SetHeader(hdrUserAgentKey, "Test Custom User agent"). 69 SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)). 70 Get(ts.URL + "/") 71 72 assert.Nil(t, err) 73 assert.Equal(t, http.StatusOK, resp.StatusCode()) 74 assert.Equal(t, "HTTP/1.1", resp.Proto()) 75 assert.Equal(t, "200 OK", resp.Status()) 76 assert.Equal(t, "TestGet: text response", resp.String()) 77 78 logResponse(t, resp) 79 } 80 81 func TestGetClientParamRequestParam(t *testing.T) { 82 ts := createGetServer(t) 83 defer ts.Close() 84 85 c := dc() 86 c.SetQueryParam("client_param", "true"). 87 SetQueryParams(map[string]string{"req_1": "jeeva", "req_3": "jeeva3"}). 88 SetDebug(true) 89 c.outputLogTo(io.Discard) 90 91 resp, err := c.R(). 92 SetQueryParams(map[string]string{"req_1": "req 1 value", "req_2": "req 2 value"}). 93 SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)). 94 SetHeader(hdrUserAgentKey, "Test Custom User agent"). 95 Get(ts.URL + "/") 96 97 assert.Nil(t, err) 98 assert.Equal(t, http.StatusOK, resp.StatusCode()) 99 assert.Equal(t, "HTTP/1.1", resp.Proto()) 100 assert.Equal(t, "200 OK", resp.Status()) 101 assert.Equal(t, "TestGet: text response", resp.String()) 102 103 logResponse(t, resp) 104 } 105 106 func TestGetRelativePath(t *testing.T) { 107 ts := createGetServer(t) 108 defer ts.Close() 109 110 c := dc() 111 c.SetBaseURL(ts.URL) 112 113 resp, err := c.R().Get("mypage2") 114 115 assert.Nil(t, err) 116 assert.Equal(t, http.StatusOK, resp.StatusCode()) 117 assert.Equal(t, "TestGet: text response from mypage2", resp.String()) 118 119 logResponse(t, resp) 120 } 121 122 func TestGet400Error(t *testing.T) { 123 ts := createGetServer(t) 124 defer ts.Close() 125 126 resp, err := dcr().Get(ts.URL + "/mypage") 127 128 assert.Nil(t, err) 129 assert.Equal(t, http.StatusBadRequest, resp.StatusCode()) 130 assert.Equal(t, "", resp.String()) 131 132 logResponse(t, resp) 133 } 134 135 func TestPostJSONStringSuccess(t *testing.T) { 136 ts := createPostServer(t) 137 defer ts.Close() 138 139 c := dc() 140 c.SetHeader(hdrContentTypeKey, "application/json; charset=utf-8"). 141 SetHeaders(map[string]string{hdrUserAgentKey: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) go-resty v0.1", hdrAcceptKey: "application/json; charset=utf-8"}) 142 143 resp, err := c.R(). 144 SetBody(`{"username":"testuser", "password":"testpass"}`). 145 Post(ts.URL + "/login") 146 147 assert.Nil(t, err) 148 assert.Equal(t, http.StatusOK, resp.StatusCode()) 149 150 logResponse(t, resp) 151 152 // PostJSONStringError 153 resp, err = c.R(). 154 SetBody(`{"username":"testuser" "password":"testpass"}`). 155 Post(ts.URL + "/login") 156 157 assert.Nil(t, err) 158 assert.Equal(t, http.StatusBadRequest, resp.StatusCode()) 159 160 logResponse(t, resp) 161 } 162 163 func TestPostJSONBytesSuccess(t *testing.T) { 164 ts := createPostServer(t) 165 defer ts.Close() 166 167 c := dc() 168 c.SetHeader(hdrContentTypeKey, "application/json; charset=utf-8"). 169 SetHeaders(map[string]string{hdrUserAgentKey: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) go-resty v0.7", hdrAcceptKey: "application/json; charset=utf-8"}) 170 171 resp, err := c.R(). 172 SetBody([]byte(`{"username":"testuser", "password":"testpass"}`)). 173 Post(ts.URL + "/login") 174 175 assert.Nil(t, err) 176 assert.Equal(t, http.StatusOK, resp.StatusCode()) 177 178 logResponse(t, resp) 179 } 180 181 func TestPostJSONBytesIoReader(t *testing.T) { 182 ts := createPostServer(t) 183 defer ts.Close() 184 185 c := dc() 186 c.SetHeader(hdrContentTypeKey, "application/json; charset=utf-8") 187 188 bodyBytes := []byte(`{"username":"testuser", "password":"testpass"}`) 189 190 resp, err := c.R(). 191 SetBody(bytes.NewReader(bodyBytes)). 192 Post(ts.URL + "/login") 193 194 assert.Nil(t, err) 195 assert.Equal(t, http.StatusOK, resp.StatusCode()) 196 197 logResponse(t, resp) 198 } 199 200 func TestPostJSONStructSuccess(t *testing.T) { 201 ts := createPostServer(t) 202 defer ts.Close() 203 204 user := &User{Username: "testuser", Password: "testpass"} 205 206 c := dc().SetJSONEscapeHTML(false) 207 resp, err := c.R(). 208 SetHeader(hdrContentTypeKey, "application/json; charset=utf-8"). 209 SetBody(user). 210 SetResult(&AuthSuccess{}). 211 Post(ts.URL + "/login") 212 213 assert.Nil(t, err) 214 assert.Equal(t, http.StatusOK, resp.StatusCode()) 215 216 t.Logf("Result Success: %q", resp.Result().(*AuthSuccess)) 217 218 logResponse(t, resp) 219 } 220 221 func TestPostJSONRPCStructSuccess(t *testing.T) { 222 ts := createPostServer(t) 223 defer ts.Close() 224 225 user := &User{Username: "testuser", Password: "testpass"} 226 227 c := dc().SetJSONEscapeHTML(false) 228 resp, err := c.R(). 229 SetHeader(hdrContentTypeKey, "application/json-rpc"). 230 SetBody(user). 231 SetResult(&AuthSuccess{}). 232 SetQueryParam("ct", "rpc"). 233 Post(ts.URL + "/login") 234 235 assert.Nil(t, err) 236 assert.Equal(t, http.StatusOK, resp.StatusCode()) 237 238 t.Logf("Result Success: %q", resp.Result().(*AuthSuccess)) 239 240 logResponse(t, resp) 241 } 242 243 func TestPostJSONStructInvalidLogin(t *testing.T) { 244 ts := createPostServer(t) 245 defer ts.Close() 246 247 c := dc() 248 c.SetDebug(false) 249 250 resp, err := c.R(). 251 SetHeader(hdrContentTypeKey, "application/json; charset=utf-8"). 252 SetBody(User{Username: "testuser", Password: "testpass1"}). 253 SetError(AuthError{}). 254 SetJSONEscapeHTML(false). 255 Post(ts.URL + "/login") 256 257 assert.Nil(t, err) 258 assert.Equal(t, http.StatusUnauthorized, resp.StatusCode()) 259 260 authError := resp.Error().(*AuthError) 261 assert.Equal(t, "unauthorized", authError.ID) 262 assert.Equal(t, "Invalid credentials", authError.Message) 263 t.Logf("Result Error: %q", resp.Error().(*AuthError)) 264 265 logResponse(t, resp) 266 } 267 268 func TestPostJSONErrorRFC7807(t *testing.T) { 269 ts := createPostServer(t) 270 defer ts.Close() 271 272 c := dc() 273 resp, err := c.R(). 274 SetHeader(hdrContentTypeKey, "application/json; charset=utf-8"). 275 SetBody(User{Username: "testuser", Password: "testpass1"}). 276 SetError(AuthError{}). 277 Post(ts.URL + "/login?ct=problem") 278 279 assert.Nil(t, err) 280 assert.Equal(t, http.StatusUnauthorized, resp.StatusCode()) 281 282 authError := resp.Error().(*AuthError) 283 assert.Equal(t, "unauthorized", authError.ID) 284 assert.Equal(t, "Invalid credentials", authError.Message) 285 t.Logf("Result Error: %q", resp.Error().(*AuthError)) 286 287 logResponse(t, resp) 288 } 289 290 func TestPostJSONMapSuccess(t *testing.T) { 291 ts := createPostServer(t) 292 defer ts.Close() 293 294 c := dc() 295 c.SetDebug(false) 296 297 resp, err := c.R(). 298 SetBody(map[string]interface{}{"username": "testuser", "password": "testpass"}). 299 SetResult(AuthSuccess{}). 300 Post(ts.URL + "/login") 301 302 assert.Nil(t, err) 303 assert.Equal(t, http.StatusOK, resp.StatusCode()) 304 305 t.Logf("Result Success: %q", resp.Result().(*AuthSuccess)) 306 307 logResponse(t, resp) 308 } 309 310 func TestPostJSONMapInvalidResponseJson(t *testing.T) { 311 ts := createPostServer(t) 312 defer ts.Close() 313 314 resp, err := dclr(). 315 SetBody(map[string]interface{}{"username": "testuser", "password": "invalidjson"}). 316 SetResult(&AuthSuccess{}). 317 Post(ts.URL + "/login") 318 319 assert.Equal(t, "invalid character '}' looking for beginning of object key string", err.Error()) 320 assert.Equal(t, http.StatusOK, resp.StatusCode()) 321 322 authSuccess := resp.Result().(*AuthSuccess) 323 assert.Equal(t, "", authSuccess.ID) 324 assert.Equal(t, "", authSuccess.Message) 325 326 t.Logf("Result Success: %q", resp.Result().(*AuthSuccess)) 327 328 logResponse(t, resp) 329 } 330 331 type brokenMarshalJSON struct{} 332 333 func (b brokenMarshalJSON) MarshalJSON() ([]byte, error) { 334 return nil, errors.New("b0rk3d") 335 } 336 337 func TestPostJSONMarshalError(t *testing.T) { 338 ts := createPostServer(t) 339 defer ts.Close() 340 341 b := brokenMarshalJSON{} 342 exp := "b0rk3d" 343 344 _, err := dclr(). 345 SetHeader(hdrContentTypeKey, "application/json"). 346 SetBody(b). 347 Post(ts.URL + "/login") 348 if err == nil { 349 t.Fatalf("expected error but got %v", err) 350 } 351 352 if !strings.Contains(err.Error(), exp) { 353 t.Errorf("expected error string %q to contain %q", err, exp) 354 } 355 } 356 357 func TestForceContentTypeForGH276andGH240(t *testing.T) { 358 ts := createPostServer(t) 359 defer ts.Close() 360 361 retried := 0 362 c := dc() 363 c.SetDebug(false) 364 c.SetRetryCount(3) 365 c.SetRetryAfter(func(*Client, *Response) (time.Duration, error) { 366 retried++ 367 return 0, nil 368 }) 369 370 resp, err := c.R(). 371 SetBody(map[string]interface{}{"username": "testuser", "password": "testpass"}). 372 SetResult(AuthSuccess{}). 373 ForceContentType("application/json"). 374 Post(ts.URL + "/login-json-html") 375 376 assert.NotNil(t, err) // expecting error due to incorrect content type from server end 377 assert.Equal(t, http.StatusOK, resp.StatusCode()) 378 assert.Equal(t, 0, retried) 379 380 t.Logf("Result Success: %q", resp.Result().(*AuthSuccess)) 381 382 logResponse(t, resp) 383 } 384 385 func TestPostXMLStringSuccess(t *testing.T) { 386 ts := createPostServer(t) 387 defer ts.Close() 388 389 c := dc() 390 c.SetDebug(false) 391 392 resp, err := c.R(). 393 SetHeader(hdrContentTypeKey, "application/xml"). 394 SetBody(`<?xml version="1.0" encoding="UTF-8"?><User><Username>testuser</Username><Password>testpass</Password></User>`). 395 SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)). 396 Post(ts.URL + "/login") 397 398 assert.Nil(t, err) 399 assert.Equal(t, http.StatusOK, resp.StatusCode()) 400 401 logResponse(t, resp) 402 } 403 404 type brokenMarshalXML struct{} 405 406 func (b brokenMarshalXML) MarshalXML(_ *xml.Encoder, _ xml.StartElement) error { 407 return errors.New("b0rk3d") 408 } 409 410 func TestPostXMLMarshalError(t *testing.T) { 411 ts := createPostServer(t) 412 defer ts.Close() 413 414 b := brokenMarshalXML{} 415 exp := "b0rk3d" 416 417 _, err := dclr(). 418 SetHeader(hdrContentTypeKey, "application/xml"). 419 SetBody(b). 420 Post(ts.URL + "/login") 421 if err == nil { 422 t.Fatalf("expected error but got %v", err) 423 } 424 425 if !strings.Contains(err.Error(), exp) { 426 t.Errorf("expected error string %q to contain %q", err, exp) 427 } 428 } 429 430 func TestPostXMLStringError(t *testing.T) { 431 ts := createPostServer(t) 432 defer ts.Close() 433 434 resp, err := dclr(). 435 SetHeader(hdrContentTypeKey, "application/xml"). 436 SetBody(`<?xml version="1.0" encoding="UTF-8"?><User><Username>testuser</Username>testpass</Password></User>`). 437 Post(ts.URL + "/login") 438 439 assert.Nil(t, err) 440 assert.Equal(t, http.StatusBadRequest, resp.StatusCode()) 441 assert.Equal(t, `<?xml version="1.0" encoding="UTF-8"?><AuthError><Id>bad_request</Id><Message>Unable to read user info</Message></AuthError>`, resp.String()) 442 443 logResponse(t, resp) 444 } 445 446 func TestPostXMLBytesSuccess(t *testing.T) { 447 ts := createPostServer(t) 448 defer ts.Close() 449 450 c := dc() 451 c.SetDebug(false) 452 453 resp, err := c.R(). 454 SetHeader(hdrContentTypeKey, "application/xml"). 455 SetBody([]byte(`<?xml version="1.0" encoding="UTF-8"?><User><Username>testuser</Username><Password>testpass</Password></User>`)). 456 SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)). 457 SetContentLength(true). 458 Post(ts.URL + "/login") 459 460 assert.Nil(t, err) 461 assert.Equal(t, http.StatusOK, resp.StatusCode()) 462 463 logResponse(t, resp) 464 } 465 466 func TestPostXMLStructSuccess(t *testing.T) { 467 ts := createPostServer(t) 468 defer ts.Close() 469 470 resp, err := dclr(). 471 SetHeader(hdrContentTypeKey, "application/xml"). 472 SetBody(User{Username: "testuser", Password: "testpass"}). 473 SetContentLength(true). 474 SetResult(&AuthSuccess{}). 475 Post(ts.URL + "/login") 476 477 assert.Nil(t, err) 478 assert.Equal(t, http.StatusOK, resp.StatusCode()) 479 480 t.Logf("Result Success: %q", resp.Result().(*AuthSuccess)) 481 482 logResponse(t, resp) 483 } 484 485 func TestPostXMLStructInvalidLogin(t *testing.T) { 486 ts := createPostServer(t) 487 defer ts.Close() 488 489 c := dc() 490 c.SetError(&AuthError{}) 491 492 resp, err := c.R(). 493 SetHeader(hdrContentTypeKey, "application/xml"). 494 SetBody(User{Username: "testuser", Password: "testpass1"}). 495 Post(ts.URL + "/login") 496 497 assert.Nil(t, err) 498 assert.Equal(t, http.StatusUnauthorized, resp.StatusCode()) 499 assert.Equal(t, resp.Header().Get("Www-Authenticate"), "Protected Realm") 500 501 t.Logf("Result Error: %q", resp.Error().(*AuthError)) 502 503 logResponse(t, resp) 504 } 505 506 func TestPostXMLStructInvalidResponseXml(t *testing.T) { 507 ts := createPostServer(t) 508 defer ts.Close() 509 510 resp, err := dclr(). 511 SetHeader(hdrContentTypeKey, "application/xml"). 512 SetBody(User{Username: "testuser", Password: "invalidxml"}). 513 SetResult(&AuthSuccess{}). 514 Post(ts.URL + "/login") 515 516 assert.Equal(t, "XML syntax error on line 1: element <Message> closed by </AuthSuccess>", err.Error()) 517 assert.Equal(t, http.StatusOK, resp.StatusCode()) 518 519 t.Logf("Result Success: %q", resp.Result().(*AuthSuccess)) 520 521 logResponse(t, resp) 522 } 523 524 func TestPostXMLMapNotSupported(t *testing.T) { 525 ts := createPostServer(t) 526 defer ts.Close() 527 528 _, err := dclr(). 529 SetHeader(hdrContentTypeKey, "application/xml"). 530 SetBody(map[string]interface{}{"Username": "testuser", "Password": "testpass"}). 531 Post(ts.URL + "/login") 532 533 assert.Equal(t, "unsupported 'Body' type/value", err.Error()) 534 } 535 536 func TestRequestBasicAuth(t *testing.T) { 537 ts := createAuthServer(t) 538 defer ts.Close() 539 540 c := dc() 541 c.SetBaseURL(ts.URL). 542 SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) 543 544 resp, err := c.R(). 545 SetBasicAuth("myuser", "basicauth"). 546 SetResult(&AuthSuccess{}). 547 Post("/login") 548 549 assert.Nil(t, err) 550 assert.Equal(t, http.StatusOK, resp.StatusCode()) 551 552 t.Logf("Result Success: %q", resp.Result().(*AuthSuccess)) 553 logResponse(t, resp) 554 } 555 556 func TestRequestBasicAuthFail(t *testing.T) { 557 ts := createAuthServer(t) 558 defer ts.Close() 559 560 c := dc() 561 c.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}). 562 SetError(AuthError{}) 563 564 resp, err := c.R(). 565 SetBasicAuth("myuser", "basicauth1"). 566 Post(ts.URL + "/login") 567 568 assert.Nil(t, err) 569 assert.Equal(t, http.StatusUnauthorized, resp.StatusCode()) 570 571 t.Logf("Result Error: %q", resp.Error().(*AuthError)) 572 logResponse(t, resp) 573 } 574 575 func TestRequestAuthToken(t *testing.T) { 576 ts := createAuthServer(t) 577 defer ts.Close() 578 579 c := dc() 580 c.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}). 581 SetAuthToken("004DDB79-6801-4587-B976-F093E6AC44FF") 582 583 resp, err := c.R(). 584 SetAuthToken("004DDB79-6801-4587-B976-F093E6AC44FF-Request"). 585 Get(ts.URL + "/profile") 586 587 assert.Nil(t, err) 588 assert.Equal(t, http.StatusOK, resp.StatusCode()) 589 } 590 591 func TestRequestAuthScheme(t *testing.T) { 592 ts := createAuthServer(t) 593 defer ts.Close() 594 595 c := dc() 596 c.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}). 597 SetAuthScheme("OAuth"). 598 SetAuthToken("004DDB79-6801-4587-B976-F093E6AC44FF") 599 600 resp, err := c.R(). 601 SetAuthScheme("Bearer"). 602 SetAuthToken("004DDB79-6801-4587-B976-F093E6AC44FF-Request"). 603 Get(ts.URL + "/profile") 604 605 assert.Nil(t, err) 606 assert.Equal(t, http.StatusOK, resp.StatusCode()) 607 } 608 609 func TestFormData(t *testing.T) { 610 ts := createFormPostServer(t) 611 defer ts.Close() 612 613 c := dc() 614 c.SetFormData(map[string]string{"zip_code": "00000", "city": "Los Angeles"}). 615 SetContentLength(true). 616 SetDebug(true) 617 c.outputLogTo(io.Discard) 618 619 resp, err := c.R(). 620 SetFormData(map[string]string{"first_name": "Jeevanandam", "last_name": "M", "zip_code": "00001"}). 621 SetBasicAuth("myuser", "mypass"). 622 Post(ts.URL + "/profile") 623 624 assert.Nil(t, err) 625 assert.Equal(t, http.StatusOK, resp.StatusCode()) 626 assert.Equal(t, "Success", resp.String()) 627 } 628 629 func TestMultiValueFormData(t *testing.T) { 630 ts := createFormPostServer(t) 631 defer ts.Close() 632 633 v := url.Values{ 634 "search_criteria": []string{"book", "glass", "pencil"}, 635 } 636 637 c := dc() 638 c.SetContentLength(true).SetDebug(true) 639 c.outputLogTo(io.Discard) 640 641 resp, err := c.R(). 642 SetQueryParamsFromValues(v). 643 Post(ts.URL + "/search") 644 645 assert.Nil(t, err) 646 assert.Equal(t, http.StatusOK, resp.StatusCode()) 647 assert.Equal(t, "Success", resp.String()) 648 } 649 650 func TestFormDataDisableWarn(t *testing.T) { 651 ts := createFormPostServer(t) 652 defer ts.Close() 653 654 c := dc() 655 c.SetFormData(map[string]string{"zip_code": "00000", "city": "Los Angeles"}). 656 SetContentLength(true). 657 SetDebug(true). 658 SetDisableWarn(true) 659 c.outputLogTo(io.Discard) 660 661 resp, err := c.R(). 662 SetFormData(map[string]string{"first_name": "Jeevanandam", "last_name": "M", "zip_code": "00001"}). 663 SetBasicAuth("myuser", "mypass"). 664 Post(ts.URL + "/profile") 665 666 assert.Nil(t, err) 667 assert.Equal(t, http.StatusOK, resp.StatusCode()) 668 assert.Equal(t, "Success", resp.String()) 669 } 670 671 func TestMultiPartUploadFile(t *testing.T) { 672 ts := createFormPostServer(t) 673 defer ts.Close() 674 defer cleanupFiles("testdata/upload") 675 676 basePath := getTestDataPath() 677 678 c := dc() 679 c.SetFormData(map[string]string{"zip_code": "00001", "city": "Los Angeles"}) 680 681 resp, err := c.R(). 682 SetFile("profile_img", filepath.Join(basePath, "test-img.png")). 683 SetContentLength(true). 684 Post(ts.URL + "/upload") 685 686 assert.Nil(t, err) 687 assert.Equal(t, http.StatusOK, resp.StatusCode()) 688 } 689 690 func TestMultiPartUploadFileError(t *testing.T) { 691 ts := createFormPostServer(t) 692 defer ts.Close() 693 defer cleanupFiles("testdata/upload") 694 695 basePath := getTestDataPath() 696 697 c := dc() 698 c.SetFormData(map[string]string{"zip_code": "00001", "city": "Los Angeles"}) 699 700 resp, err := c.R(). 701 SetFile("profile_img", filepath.Join(basePath, "test-img-not-exists.png")). 702 Post(ts.URL + "/upload") 703 704 if err == nil { 705 t.Errorf("Expected [%v], got [%v]", nil, err) 706 } 707 if resp != nil { 708 t.Errorf("Expected [%v], got [%v]", nil, resp) 709 } 710 } 711 712 func TestMultiPartUploadFiles(t *testing.T) { 713 ts := createFormPostServer(t) 714 defer ts.Close() 715 defer cleanupFiles("testdata/upload") 716 717 basePath := getTestDataPath() 718 719 resp, err := dclr(). 720 SetFormDataFromValues(url.Values{ 721 "first_name": []string{"Jeevanandam"}, 722 "last_name": []string{"M"}, 723 }). 724 SetFiles(map[string]string{"profile_img": filepath.Join(basePath, "test-img.png"), "notes": filepath.Join(basePath, "text-file.txt")}). 725 Post(ts.URL + "/upload") 726 727 responseStr := resp.String() 728 729 assert.Nil(t, err) 730 assert.Equal(t, http.StatusOK, resp.StatusCode()) 731 assert.True(t, strings.Contains(responseStr, "test-img.png")) 732 assert.True(t, strings.Contains(responseStr, "text-file.txt")) 733 } 734 735 func TestMultiPartIoReaderFiles(t *testing.T) { 736 ts := createFormPostServer(t) 737 defer ts.Close() 738 defer cleanupFiles("testdata/upload") 739 740 basePath := getTestDataPath() 741 profileImgBytes, _ := os.ReadFile(filepath.Join(basePath, "test-img.png")) 742 notesBytes, _ := os.ReadFile(filepath.Join(basePath, "text-file.txt")) 743 744 // Just info values 745 file := File{ 746 Name: "test_file_name.jpg", 747 ParamName: "test_param", 748 Reader: bytes.NewBuffer([]byte("test bytes")), 749 } 750 t.Logf("File Info: %v", file.String()) 751 752 resp, err := dclr(). 753 SetFormData(map[string]string{"first_name": "Jeevanandam", "last_name": "M"}). 754 SetFileReader("profile_img", "test-img.png", bytes.NewReader(profileImgBytes)). 755 SetFileReader("notes", "text-file.txt", bytes.NewReader(notesBytes)). 756 Post(ts.URL + "/upload") 757 758 responseStr := resp.String() 759 760 assert.Nil(t, err) 761 assert.Equal(t, http.StatusOK, resp.StatusCode()) 762 assert.True(t, strings.Contains(responseStr, "test-img.png")) 763 assert.True(t, strings.Contains(responseStr, "text-file.txt")) 764 } 765 766 func TestMultiPartUploadFileNotOnGetOrDelete(t *testing.T) { 767 ts := createFormPostServer(t) 768 defer ts.Close() 769 defer cleanupFiles("testdata/upload") 770 771 basePath := getTestDataPath() 772 773 _, err := dclr(). 774 SetFile("profile_img", filepath.Join(basePath, "test-img.png")). 775 Get(ts.URL + "/upload") 776 777 assert.Equal(t, "multipart content is not allowed in HTTP verb [GET]", err.Error()) 778 779 _, err = dclr(). 780 SetFile("profile_img", filepath.Join(basePath, "test-img.png")). 781 Delete(ts.URL + "/upload") 782 783 assert.Equal(t, "multipart content is not allowed in HTTP verb [DELETE]", err.Error()) 784 } 785 786 func TestMultiPartFormData(t *testing.T) { 787 ts := createFormPostServer(t) 788 defer ts.Close() 789 resp, err := dclr(). 790 SetMultipartFormData(map[string]string{"first_name": "Jeevanandam", "last_name": "M", "zip_code": "00001"}). 791 SetBasicAuth("myuser", "mypass"). 792 Post(ts.URL + "/profile") 793 794 assert.Nil(t, err) 795 assert.Equal(t, http.StatusOK, resp.StatusCode()) 796 assert.Equal(t, "Success", resp.String()) 797 } 798 799 func TestMultiPartMultipartField(t *testing.T) { 800 ts := createFormPostServer(t) 801 defer ts.Close() 802 defer cleanupFiles("testdata/upload") 803 804 jsonBytes := []byte(`{"input": {"name": "Uploaded document", "_filename" : ["file.txt"]}}`) 805 806 resp, err := dclr(). 807 SetFormDataFromValues(url.Values{ 808 "first_name": []string{"Jeevanandam"}, 809 "last_name": []string{"M"}, 810 }). 811 SetMultipartField("uploadManifest", "upload-file.json", "application/json", bytes.NewReader(jsonBytes)). 812 Post(ts.URL + "/upload") 813 814 responseStr := resp.String() 815 816 assert.Nil(t, err) 817 assert.Equal(t, http.StatusOK, resp.StatusCode()) 818 assert.True(t, strings.Contains(responseStr, "upload-file.json")) 819 } 820 821 func TestMultiPartMultipartFields(t *testing.T) { 822 ts := createFormPostServer(t) 823 defer ts.Close() 824 defer cleanupFiles("testdata/upload") 825 826 jsonStr1 := `{"input": {"name": "Uploaded document 1", "_filename" : ["file1.txt"]}}` 827 jsonStr2 := `{"input": {"name": "Uploaded document 2", "_filename" : ["file2.txt"]}}` 828 829 fields := []*MultipartField{ 830 { 831 Param: "uploadManifest1", 832 FileName: "upload-file-1.json", 833 ContentType: "application/json", 834 Reader: strings.NewReader(jsonStr1), 835 }, 836 { 837 Param: "uploadManifest2", 838 FileName: "upload-file-2.json", 839 ContentType: "application/json", 840 Reader: strings.NewReader(jsonStr2), 841 }, 842 { 843 Param: "uploadManifest3", 844 ContentType: "application/json", 845 Reader: strings.NewReader(jsonStr2), 846 }, 847 } 848 849 resp, err := dclr(). 850 SetFormData(map[string]string{"first_name": "Jeevanandam", "last_name": "M"}). 851 SetMultipartFields(fields...). 852 Post(ts.URL + "/upload") 853 854 responseStr := resp.String() 855 856 assert.Nil(t, err) 857 assert.Equal(t, http.StatusOK, resp.StatusCode()) 858 assert.True(t, strings.Contains(responseStr, "upload-file-1.json")) 859 assert.True(t, strings.Contains(responseStr, "upload-file-2.json")) 860 } 861 862 func TestGetWithCookie(t *testing.T) { 863 ts := createGetServer(t) 864 defer ts.Close() 865 866 c := dcl() 867 c.SetBaseURL(ts.URL) 868 c.SetCookies(&http.Cookie{ 869 Name: "go-resty-1", 870 Value: "This is cookie 1 value", 871 }) 872 873 resp, err := c.R(). 874 SetCookie(&http.Cookie{ 875 Name: "go-resty-2", 876 Value: "This is cookie 2 value", 877 }). 878 SetCookies([]*http.Cookie{ 879 { 880 Name: "go-resty-1", 881 Value: "This is cookie 1 value additional append", 882 }, 883 }). 884 Get("mypage2") 885 886 assert.Nil(t, err) 887 assert.Equal(t, http.StatusOK, resp.StatusCode()) 888 assert.Equal(t, "TestGet: text response from mypage2", resp.String()) 889 890 logResponse(t, resp) 891 } 892 893 func TestGetWithCookies(t *testing.T) { 894 ts := createGetServer(t) 895 defer ts.Close() 896 897 c := dc() 898 c.SetBaseURL(ts.URL).SetDebug(true) 899 900 tu, _ := url.Parse(ts.URL) 901 c.GetClient().Jar.SetCookies(tu, []*http.Cookie{ 902 { 903 Name: "jar-go-resty-1", 904 Value: "From Jar - This is cookie 1 value", 905 }, 906 { 907 Name: "jar-go-resty-2", 908 Value: "From Jar - This is cookie 2 value", 909 }, 910 }) 911 912 resp, err := c.R().SetHeader("Cookie", "").Get("mypage2") 913 assert.Nil(t, err) 914 assert.Equal(t, http.StatusOK, resp.StatusCode()) 915 916 // Client cookies 917 c.SetCookies( 918 &http.Cookie{Name: "go-resty-1", Value: "This is cookie 1 value"}, 919 &http.Cookie{Name: "go-resty-2", Value: "This is cookie 2 value"}) 920 921 resp, err = c.R(). 922 SetCookie(&http.Cookie{ 923 Name: "req-go-resty-1", 924 Value: "This is request cookie 1 value additional append", 925 }). 926 Get("mypage2") 927 928 assert.Nil(t, err) 929 assert.Equal(t, http.StatusOK, resp.StatusCode()) 930 assert.Equal(t, "TestGet: text response from mypage2", resp.String()) 931 932 logResponse(t, resp) 933 } 934 935 func TestPutPlainString(t *testing.T) { 936 ts := createGenServer(t) 937 defer ts.Close() 938 939 resp, err := dc().R(). 940 SetBody("This is plain text body to server"). 941 Put(ts.URL + "/plaintext") 942 943 assert.Nil(t, err) 944 assert.Equal(t, http.StatusOK, resp.StatusCode()) 945 assert.Equal(t, "TestPut: plain text response", resp.String()) 946 } 947 948 func TestPutJSONString(t *testing.T) { 949 ts := createGenServer(t) 950 defer ts.Close() 951 952 client := dc() 953 954 client.OnBeforeRequest(func(c *Client, r *Request) error { 955 r.SetHeader("X-Custom-Request-Middleware", "OnBeforeRequest middleware") 956 return nil 957 }) 958 client.OnBeforeRequest(func(c *Client, r *Request) error { 959 c.SetContentLength(true) 960 r.SetHeader("X-ContentLength", "OnBeforeRequest ContentLength set") 961 return nil 962 }) 963 964 client.SetDebug(true) 965 client.outputLogTo(io.Discard) 966 967 resp, err := client.R(). 968 SetHeaders(map[string]string{hdrContentTypeKey: "application/json; charset=utf-8", hdrAcceptKey: "application/json; charset=utf-8"}). 969 SetBody(`{"content":"json content sending to server"}`). 970 Put(ts.URL + "/json") 971 972 assert.Nil(t, err) 973 assert.Equal(t, http.StatusOK, resp.StatusCode()) 974 assert.Equal(t, `{"response":"json response"}`, resp.String()) 975 } 976 977 func TestPutXMLString(t *testing.T) { 978 ts := createGenServer(t) 979 defer ts.Close() 980 981 resp, err := dc().R(). 982 SetHeaders(map[string]string{hdrContentTypeKey: "application/xml", hdrAcceptKey: "application/xml"}). 983 SetBody(`<?xml version="1.0" encoding="UTF-8"?><Request>XML Content sending to server</Request>`). 984 Put(ts.URL + "/xml") 985 986 assert.Nil(t, err) 987 assert.Equal(t, http.StatusOK, resp.StatusCode()) 988 assert.Equal(t, `<?xml version="1.0" encoding="UTF-8"?><Response>XML response</Response>`, resp.String()) 989 } 990 991 func TestOnBeforeMiddleware(t *testing.T) { 992 ts := createGenServer(t) 993 defer ts.Close() 994 995 c := dc() 996 c.OnBeforeRequest(func(c *Client, r *Request) error { 997 r.SetHeader("X-Custom-Request-Middleware", "OnBeforeRequest middleware") 998 return nil 999 }) 1000 c.OnBeforeRequest(func(c *Client, r *Request) error { 1001 c.SetContentLength(true) 1002 r.SetHeader("X-ContentLength", "OnBeforeRequest ContentLength set") 1003 return nil 1004 }) 1005 1006 resp, err := c.R(). 1007 SetBody("OnBeforeRequest: This is plain text body to server"). 1008 Put(ts.URL + "/plaintext") 1009 1010 assert.Nil(t, err) 1011 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1012 assert.Equal(t, "TestPut: plain text response", resp.String()) 1013 } 1014 1015 func TestHTTPAutoRedirectUpTo10(t *testing.T) { 1016 ts := createRedirectServer(t) 1017 defer ts.Close() 1018 1019 _, err := dc().R().Get(ts.URL + "/redirect-1") 1020 1021 assert.True(t, "Get /redirect-11: stopped after 10 redirects" == err.Error() || 1022 "Get \"/redirect-11\": stopped after 10 redirects" == err.Error()) 1023 } 1024 1025 func TestHostCheckRedirectPolicy(t *testing.T) { 1026 ts := createRedirectServer(t) 1027 defer ts.Close() 1028 1029 c := dc(). 1030 SetRedirectPolicy(DomainCheckRedirectPolicy("127.0.0.1")) 1031 1032 _, err := c.R().Get(ts.URL + "/redirect-host-check-1") 1033 1034 assert.NotNil(t, err) 1035 assert.True(t, strings.Contains(err.Error(), "redirect is not allowed as per DomainCheckRedirectPolicy")) 1036 } 1037 1038 func TestHeadMethod(t *testing.T) { 1039 ts := createGetServer(t) 1040 defer ts.Close() 1041 1042 resp, err := dclr().Head(ts.URL + "/") 1043 1044 assert.Nil(t, err) 1045 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1046 } 1047 1048 func TestOptionsMethod(t *testing.T) { 1049 ts := createGenServer(t) 1050 defer ts.Close() 1051 1052 resp, err := dclr().Options(ts.URL + "/options") 1053 1054 assert.Nil(t, err) 1055 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1056 assert.Equal(t, resp.Header().Get("Access-Control-Expose-Headers"), "x-go-resty-id") 1057 } 1058 1059 func TestPatchMethod(t *testing.T) { 1060 ts := createGenServer(t) 1061 defer ts.Close() 1062 1063 resp, err := dclr().Patch(ts.URL + "/patch") 1064 1065 assert.Nil(t, err) 1066 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1067 1068 resp.body = nil 1069 assert.Equal(t, "", resp.String()) 1070 } 1071 1072 func TestSendMethod(t *testing.T) { 1073 ts := createGenServer(t) 1074 defer ts.Close() 1075 1076 t.Run("send-get", func(t *testing.T) { 1077 req := dclr() 1078 req.Method = http.MethodGet 1079 req.URL = ts.URL + "/gzip-test" 1080 1081 resp, err := req.Send() 1082 1083 assert.Nil(t, err) 1084 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1085 1086 assert.Equal(t, "This is Gzip response testing", resp.String()) 1087 }) 1088 1089 t.Run("send-options", func(t *testing.T) { 1090 req := dclr() 1091 req.Method = http.MethodOptions 1092 req.URL = ts.URL + "/options" 1093 1094 resp, err := req.Send() 1095 1096 assert.Nil(t, err) 1097 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1098 1099 assert.Equal(t, "", resp.String()) 1100 assert.Equal(t, "x-go-resty-id", resp.Header().Get("Access-Control-Expose-Headers")) 1101 }) 1102 1103 t.Run("send-patch", func(t *testing.T) { 1104 req := dclr() 1105 req.Method = http.MethodPatch 1106 req.URL = ts.URL + "/patch" 1107 1108 resp, err := req.Send() 1109 1110 assert.Nil(t, err) 1111 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1112 1113 assert.Equal(t, "", resp.String()) 1114 }) 1115 1116 t.Run("send-put", func(t *testing.T) { 1117 req := dclr() 1118 req.Method = http.MethodPut 1119 req.URL = ts.URL + "/plaintext" 1120 1121 resp, err := req.Send() 1122 1123 assert.Nil(t, err) 1124 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1125 1126 assert.Equal(t, "TestPut: plain text response", resp.String()) 1127 }) 1128 } 1129 1130 func TestRawFileUploadByBody(t *testing.T) { 1131 ts := createFormPostServer(t) 1132 defer ts.Close() 1133 1134 file, err := os.Open(filepath.Join(getTestDataPath(), "test-img.png")) 1135 assert.Nil(t, err) 1136 fileBytes, err := io.ReadAll(file) 1137 assert.Nil(t, err) 1138 1139 resp, err := dclr(). 1140 SetBody(fileBytes). 1141 SetContentLength(true). 1142 SetAuthToken("004DDB79-6801-4587-B976-F093E6AC44FF"). 1143 Put(ts.URL + "/raw-upload") 1144 1145 assert.Nil(t, err) 1146 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1147 assert.Equal(t, "image/png", resp.Request.Header.Get(hdrContentTypeKey)) 1148 } 1149 1150 func TestProxySetting(t *testing.T) { 1151 c := dc() 1152 1153 transport, err := c.transport() 1154 1155 assert.Nil(t, err) 1156 1157 assert.Equal(t, false, c.IsProxySet()) 1158 assert.NotNil(t, transport.Proxy) 1159 1160 c.SetProxy("http://sampleproxy:8888") 1161 assert.True(t, c.IsProxySet()) 1162 assert.NotNil(t, transport.Proxy) 1163 1164 c.SetProxy("//not.a.user@%66%6f%6f.com:8888") 1165 assert.True(t, c.IsProxySet()) 1166 assert.NotNil(t, transport.Proxy) 1167 1168 c.SetProxy("http://sampleproxy:8888") 1169 assert.True(t, c.IsProxySet()) 1170 c.RemoveProxy() 1171 assert.Nil(t, c.proxyURL) 1172 assert.Nil(t, transport.Proxy) 1173 } 1174 1175 func TestGetClient(t *testing.T) { 1176 client := New() 1177 custom := New() 1178 customClient := custom.GetClient() 1179 1180 assert.NotNil(t, customClient) 1181 assert.NotEqual(t, client, http.DefaultClient) 1182 assert.NotEqual(t, customClient, http.DefaultClient) 1183 assert.NotEqual(t, client, customClient) 1184 } 1185 1186 func TestIncorrectURL(t *testing.T) { 1187 c := dc() 1188 _, err := c.R().Get("//not.a.user@%66%6f%6f.com/just/a/path/also") 1189 assert.True(t, strings.Contains(err.Error(), "parse //not.a.user@%66%6f%6f.com/just/a/path/also") || 1190 strings.Contains(err.Error(), "parse \"//not.a.user@%66%6f%6f.com/just/a/path/also\"")) 1191 1192 c.SetBaseURL("//not.a.user@%66%6f%6f.com") 1193 _, err1 := c.R().Get("/just/a/path/also") 1194 assert.True(t, strings.Contains(err1.Error(), "parse //not.a.user@%66%6f%6f.com/just/a/path/also") || 1195 strings.Contains(err1.Error(), "parse \"//not.a.user@%66%6f%6f.com/just/a/path/also\"")) 1196 } 1197 1198 func TestDetectContentTypeForPointer(t *testing.T) { 1199 ts := createPostServer(t) 1200 defer ts.Close() 1201 1202 user := &User{Username: "testuser", Password: "testpass"} 1203 1204 resp, err := dclr(). 1205 SetBody(user). 1206 SetResult(AuthSuccess{}). 1207 Post(ts.URL + "/login") 1208 1209 assert.Nil(t, err) 1210 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1211 1212 t.Logf("Result Success: %q", resp.Result().(*AuthSuccess)) 1213 1214 logResponse(t, resp) 1215 } 1216 1217 type ExampleUser struct { 1218 FirstName string `json:"frist_name"` 1219 LastName string `json:"last_name"` 1220 ZipCode string `json:"zip_code"` 1221 } 1222 1223 func TestDetectContentTypeForPointerWithSlice(t *testing.T) { 1224 ts := createPostServer(t) 1225 defer ts.Close() 1226 1227 users := &[]ExampleUser{ 1228 {FirstName: "firstname1", LastName: "lastname1", ZipCode: "10001"}, 1229 {FirstName: "firstname2", LastName: "lastname3", ZipCode: "10002"}, 1230 {FirstName: "firstname3", LastName: "lastname3", ZipCode: "10003"}, 1231 } 1232 1233 resp, err := dclr(). 1234 SetBody(users). 1235 Post(ts.URL + "/users") 1236 1237 assert.Nil(t, err) 1238 assert.Equal(t, http.StatusAccepted, resp.StatusCode()) 1239 1240 t.Logf("Result Success: %q", resp) 1241 1242 logResponse(t, resp) 1243 } 1244 1245 func TestDetectContentTypeForPointerWithSliceMap(t *testing.T) { 1246 ts := createPostServer(t) 1247 defer ts.Close() 1248 1249 usersmap := map[string]interface{}{ 1250 "user1": ExampleUser{FirstName: "firstname1", LastName: "lastname1", ZipCode: "10001"}, 1251 "user2": &ExampleUser{FirstName: "firstname2", LastName: "lastname3", ZipCode: "10002"}, 1252 "user3": ExampleUser{FirstName: "firstname3", LastName: "lastname3", ZipCode: "10003"}, 1253 } 1254 1255 var users []map[string]interface{} 1256 users = append(users, usersmap) 1257 1258 resp, err := dclr(). 1259 SetBody(&users). 1260 Post(ts.URL + "/usersmap") 1261 1262 assert.Nil(t, err) 1263 assert.Equal(t, http.StatusAccepted, resp.StatusCode()) 1264 1265 t.Logf("Result Success: %q", resp) 1266 1267 logResponse(t, resp) 1268 } 1269 1270 func TestDetectContentTypeForSlice(t *testing.T) { 1271 ts := createPostServer(t) 1272 defer ts.Close() 1273 1274 users := []ExampleUser{ 1275 {FirstName: "firstname1", LastName: "lastname1", ZipCode: "10001"}, 1276 {FirstName: "firstname2", LastName: "lastname3", ZipCode: "10002"}, 1277 {FirstName: "firstname3", LastName: "lastname3", ZipCode: "10003"}, 1278 } 1279 1280 resp, err := dclr(). 1281 SetBody(users). 1282 Post(ts.URL + "/users") 1283 1284 assert.Nil(t, err) 1285 assert.Equal(t, http.StatusAccepted, resp.StatusCode()) 1286 1287 t.Logf("Result Success: %q", resp) 1288 1289 logResponse(t, resp) 1290 } 1291 1292 func TestMultiParamsQueryString(t *testing.T) { 1293 ts1 := createGetServer(t) 1294 defer ts1.Close() 1295 1296 client := dc() 1297 req1 := client.R() 1298 1299 client.SetQueryParam("status", "open") 1300 1301 _, _ = req1.SetQueryParam("status", "pending"). 1302 Get(ts1.URL) 1303 1304 assert.True(t, strings.Contains(req1.URL, "status=pending")) 1305 // pending overrides open 1306 assert.Equal(t, false, strings.Contains(req1.URL, "status=open")) 1307 1308 _, _ = req1.SetQueryParam("status", "approved"). 1309 Get(ts1.URL) 1310 1311 assert.True(t, strings.Contains(req1.URL, "status=approved")) 1312 // approved overrides pending 1313 assert.Equal(t, false, strings.Contains(req1.URL, "status=pending")) 1314 1315 ts2 := createGetServer(t) 1316 defer ts2.Close() 1317 1318 req2 := client.R() 1319 1320 v := url.Values{ 1321 "status": []string{"pending", "approved", "reject"}, 1322 } 1323 1324 _, _ = req2.SetQueryParamsFromValues(v).Get(ts2.URL) 1325 1326 assert.True(t, strings.Contains(req2.URL, "status=pending")) 1327 assert.True(t, strings.Contains(req2.URL, "status=approved")) 1328 assert.True(t, strings.Contains(req2.URL, "status=reject")) 1329 1330 // because it's removed by key 1331 assert.Equal(t, false, strings.Contains(req2.URL, "status=open")) 1332 } 1333 1334 func TestSetQueryStringTypical(t *testing.T) { 1335 ts := createGetServer(t) 1336 defer ts.Close() 1337 1338 resp, err := dclr(). 1339 SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more"). 1340 Get(ts.URL) 1341 1342 assert.Nil(t, err) 1343 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1344 assert.Equal(t, "200 OK", resp.Status()) 1345 assert.Equal(t, "TestGet: text response", resp.String()) 1346 1347 resp, err = dclr(). 1348 SetQueryString("&%%amp;"). 1349 Get(ts.URL) 1350 1351 assert.Nil(t, err) 1352 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1353 assert.Equal(t, "200 OK", resp.Status()) 1354 assert.Equal(t, "TestGet: text response", resp.String()) 1355 } 1356 1357 func TestSetHeaderVerbatim(t *testing.T) { 1358 ts := createPostServer(t) 1359 defer ts.Close() 1360 1361 r := dclr(). 1362 SetHeaderVerbatim("header-lowercase", "value_lowercase"). 1363 SetHeader("header-lowercase", "value_standard") 1364 1365 assert.Equal(t, "value_lowercase", strings.Join(r.Header["header-lowercase"], "")) //nolint 1366 assert.Equal(t, "value_standard", r.Header.Get("Header-Lowercase")) 1367 } 1368 1369 func TestSetHeaderMultipleValue(t *testing.T) { 1370 ts := createPostServer(t) 1371 defer ts.Close() 1372 1373 r := dclr(). 1374 SetHeaderMultiValues(map[string][]string{ 1375 "Content": {"text/*", "text/html", "*"}, 1376 "Authorization": {"Bearer xyz"}, 1377 }) 1378 assert.Equal(t, "text/*, text/html, *", r.Header.Get("content")) 1379 assert.Equal(t, "Bearer xyz", r.Header.Get("authorization")) 1380 } 1381 1382 func TestOutputFileWithBaseDirAndRelativePath(t *testing.T) { 1383 ts := createGetServer(t) 1384 defer ts.Close() 1385 defer cleanupFiles("testdata/dir-sample") 1386 1387 client := dc(). 1388 SetRedirectPolicy(FlexibleRedirectPolicy(10)). 1389 SetOutputDirectory(filepath.Join(getTestDataPath(), "dir-sample")). 1390 SetDebug(true) 1391 client.outputLogTo(io.Discard) 1392 1393 resp, err := client.R(). 1394 SetOutput("go-resty/test-img-success.png"). 1395 Get(ts.URL + "/my-image.png") 1396 1397 assert.Nil(t, err) 1398 assert.True(t, resp.Size() != 0) 1399 assert.True(t, resp.Time() > 0) 1400 } 1401 1402 func TestOutputFileWithBaseDirError(t *testing.T) { 1403 c := dc().SetRedirectPolicy(FlexibleRedirectPolicy(10)). 1404 SetOutputDirectory(filepath.Join(getTestDataPath(), `go-resty\0`)) 1405 1406 _ = c 1407 } 1408 1409 func TestOutputPathDirNotExists(t *testing.T) { 1410 ts := createGetServer(t) 1411 defer ts.Close() 1412 defer cleanupFiles(filepath.Join("testdata", "not-exists-dir")) 1413 1414 client := dc(). 1415 SetRedirectPolicy(FlexibleRedirectPolicy(10)). 1416 SetOutputDirectory(filepath.Join(getTestDataPath(), "not-exists-dir")) 1417 1418 resp, err := client.R(). 1419 SetOutput("test-img-success.png"). 1420 Get(ts.URL + "/my-image.png") 1421 1422 assert.Nil(t, err) 1423 assert.True(t, resp.Size() != 0) 1424 assert.True(t, resp.Time() > 0) 1425 } 1426 1427 func TestOutputFileAbsPath(t *testing.T) { 1428 ts := createGetServer(t) 1429 defer ts.Close() 1430 defer cleanupFiles(filepath.Join("testdata", "go-resty")) 1431 1432 _, err := dcr(). 1433 SetOutput(filepath.Join(getTestDataPath(), "go-resty", "test-img-success-2.png")). 1434 Get(ts.URL + "/my-image.png") 1435 1436 assert.Nil(t, err) 1437 } 1438 1439 func TestContextInternal(t *testing.T) { 1440 ts := createGetServer(t) 1441 defer ts.Close() 1442 1443 r := dc().R(). 1444 SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)) 1445 1446 resp, err := r.Get(ts.URL + "/") 1447 1448 assert.Nil(t, err) 1449 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1450 } 1451 1452 func TestSRV(t *testing.T) { 1453 c := dc(). 1454 SetRedirectPolicy(FlexibleRedirectPolicy(20)). 1455 SetScheme("http") 1456 1457 r := c.R().SetSRV(&SRVRecord{Service: "xmpp-server", Domain: "google.com"}) 1458 1459 assert.Equal(t, "xmpp-server", r.SRV.Service) 1460 assert.Equal(t, "google.com", r.SRV.Domain) 1461 1462 resp, err := r.Get("/") 1463 assert.Nil(t, err) 1464 assert.NotNil(t, resp) 1465 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1466 } 1467 1468 func TestSRVInvalidService(t *testing.T) { 1469 _, err := dc().R(). 1470 SetSRV(&SRVRecord{"nonexistantservice", "sampledomain"}). 1471 Get("/") 1472 1473 assert.NotNil(t, err) 1474 _, ok := err.(*net.DNSError) 1475 assert.True(t, ok) 1476 } 1477 1478 func TestRequestDoNotParseResponse(t *testing.T) { 1479 ts := createGetServer(t) 1480 defer ts.Close() 1481 1482 client := dc().SetDoNotParseResponse(true) 1483 resp, err := client.R(). 1484 SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)). 1485 Get(ts.URL + "/") 1486 1487 assert.Nil(t, err) 1488 1489 buf := acquireBuffer() 1490 defer releaseBuffer(buf) 1491 _, _ = io.Copy(buf, resp.RawBody()) 1492 1493 assert.Equal(t, "TestGet: text response", buf.String()) 1494 _ = resp.RawBody().Close() 1495 1496 // Manually setting RawResponse as nil 1497 resp, err = dc().R(). 1498 SetDoNotParseResponse(true). 1499 Get(ts.URL + "/") 1500 1501 assert.Nil(t, err) 1502 1503 resp.RawResponse = nil 1504 assert.Nil(t, resp.RawBody()) 1505 } 1506 1507 type noCtTest struct { 1508 Response string `json:"response"` 1509 } 1510 1511 func TestRequestExpectContentTypeTest(t *testing.T) { 1512 ts := createGenServer(t) 1513 defer ts.Close() 1514 1515 c := dc() 1516 resp, err := c.R(). 1517 SetResult(noCtTest{}). 1518 ExpectContentType("application/json"). 1519 Get(ts.URL + "/json-no-set") 1520 1521 assert.Nil(t, err) 1522 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1523 assert.NotNil(t, resp.Result()) 1524 assert.Equal(t, "json response no content type set", resp.Result().(*noCtTest).Response) 1525 1526 assert.Equal(t, "", firstNonEmpty("", "")) 1527 } 1528 1529 func TestGetPathParamAndPathParams(t *testing.T) { 1530 ts := createGetServer(t) 1531 defer ts.Close() 1532 1533 c := dc(). 1534 SetBaseURL(ts.URL). 1535 SetPathParam("userId", "sample@sample.com") 1536 1537 resp, err := c.R().SetPathParam("subAccountId", "100002"). 1538 Get("/v1/users/{userId}/{subAccountId}/details") 1539 1540 assert.Nil(t, err) 1541 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1542 assert.True(t, strings.Contains(resp.String(), "TestGetPathParams: text response")) 1543 assert.True(t, strings.Contains(resp.String(), "/v1/users/sample@sample.com/100002/details")) 1544 1545 logResponse(t, resp) 1546 } 1547 1548 func TestReportMethodSupportsPayload(t *testing.T) { 1549 ts := createGenServer(t) 1550 defer ts.Close() 1551 1552 c := dc() 1553 resp, err := c.R(). 1554 SetBody("body"). 1555 Execute("REPORT", ts.URL+"/report") 1556 1557 assert.Nil(t, err) 1558 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1559 } 1560 1561 func TestRequestQueryStringOrder(t *testing.T) { 1562 ts := createGetServer(t) 1563 defer ts.Close() 1564 1565 resp, err := New().R(). 1566 SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more"). 1567 Get(ts.URL + "/?UniqueId=ead1d0ed-XXX-XXX-XXX-abb7612b3146&Translate=false&tempauth=eyJ0eXAiOiJKV1QiLC...HZEhwVnJ1d0NSUGVLaUpSaVNLRG5scz0&ApiVersion=2.0") 1568 1569 assert.Nil(t, err) 1570 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1571 assert.Equal(t, "200 OK", resp.Status()) 1572 assert.NotNil(t, resp.Body()) 1573 assert.Equal(t, "TestGet: text response", resp.String()) 1574 1575 logResponse(t, resp) 1576 } 1577 1578 func TestRequestOverridesClientAuthorizationHeader(t *testing.T) { 1579 ts := createAuthServer(t) 1580 defer ts.Close() 1581 1582 c := dc() 1583 c.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}). 1584 SetHeader("Authorization", "some token"). 1585 SetBaseURL(ts.URL + "/") 1586 1587 resp, err := c.R(). 1588 SetHeader("Authorization", "Bearer 004DDB79-6801-4587-B976-F093E6AC44FF"). 1589 Get("/profile") 1590 1591 assert.Nil(t, err) 1592 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1593 } 1594 1595 func TestRequestFileUploadAsReader(t *testing.T) { 1596 ts := createFilePostServer(t) 1597 defer ts.Close() 1598 1599 file, _ := os.Open(filepath.Join(getTestDataPath(), "test-img.png")) 1600 defer iox.Close(file) 1601 1602 resp, err := dclr(). 1603 SetBody(file). 1604 SetHeader("Content-Type", "image/png"). 1605 Post(ts.URL + "/upload") 1606 1607 assert.Nil(t, err) 1608 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1609 assert.True(t, strings.Contains(resp.String(), "File Uploaded successfully")) 1610 1611 file, _ = os.Open(filepath.Join(getTestDataPath(), "test-img.png")) 1612 defer iox.Close(file) 1613 1614 resp, err = dclr(). 1615 SetBody(file). 1616 SetHeader("Content-Type", "image/png"). 1617 SetContentLength(true). 1618 Post(ts.URL + "/upload") 1619 1620 assert.Nil(t, err) 1621 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1622 assert.True(t, strings.Contains(resp.String(), "File Uploaded successfully")) 1623 } 1624 1625 func TestHostHeaderOverride(t *testing.T) { 1626 ts := createGetServer(t) 1627 defer ts.Close() 1628 1629 resp, err := dc().R(). 1630 SetHeader("Host", "myhostname"). 1631 Get(ts.URL + "/host-header") 1632 1633 assert.Nil(t, err) 1634 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1635 assert.Equal(t, "200 OK", resp.Status()) 1636 assert.NotNil(t, resp.Body()) 1637 assert.Equal(t, "myhostname", resp.String()) 1638 1639 logResponse(t, resp) 1640 } 1641 1642 func TestPathParamURLInput(t *testing.T) { 1643 ts := createGetServer(t) 1644 defer ts.Close() 1645 1646 c := dc().SetDebug(true). 1647 SetBaseURL(ts.URL). 1648 SetPathParams(map[string]string{ 1649 "userId": "sample@sample.com", 1650 }) 1651 1652 resp, err := c.R(). 1653 SetPathParams(map[string]string{ 1654 "subAccountId": "100002", 1655 "website": "https://example.com", 1656 }).Get("/v1/users/{userId}/{subAccountId}/{website}") 1657 1658 assert.Nil(t, err) 1659 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1660 assert.True(t, strings.Contains(resp.String(), "TestPathParamURLInput: text response")) 1661 assert.True(t, strings.Contains(resp.String(), "/v1/users/sample@sample.com/100002/https:%2F%2Fexample.com")) 1662 1663 logResponse(t, resp) 1664 } 1665 1666 // This test case is kind of pass always 1667 func TestTraceInfo(t *testing.T) { 1668 ts := createGetServer(t) 1669 defer ts.Close() 1670 1671 serverAddr := ts.URL[strings.LastIndex(ts.URL, "/")+1:] 1672 1673 client := dc() 1674 client.SetBaseURL(ts.URL).SetTrace(true) 1675 for _, u := range []string{"/", "/json", "/long-text", "/long-json"} { 1676 resp, err := client.R().Get(u) 1677 assert.Nil(t, err) 1678 assert.NotNil(t, resp) 1679 1680 tr := resp.Request.TraceInfo() 1681 assert.True(t, tr.DNSLookup >= 0) 1682 assert.True(t, tr.ConnTime >= 0) 1683 assert.True(t, tr.TLSHandshake >= 0) 1684 assert.True(t, tr.ServerTime >= 0) 1685 assert.True(t, tr.ResponseTime >= 0) 1686 assert.True(t, tr.TotalTime >= 0) 1687 assert.True(t, tr.TotalTime < time.Hour) 1688 assert.True(t, tr.TotalTime == resp.Time()) 1689 assert.Equal(t, tr.RemoteAddr.String(), serverAddr) 1690 } 1691 1692 client.SetTrace(false) 1693 1694 for _, u := range []string{"/", "/json", "/long-text", "/long-json"} { 1695 resp, err := client.R().SetTrace(true).Get(u) 1696 assert.Nil(t, err) 1697 assert.NotNil(t, resp) 1698 1699 tr := resp.Request.TraceInfo() 1700 assert.True(t, tr.DNSLookup >= 0) 1701 assert.True(t, tr.ConnTime >= 0) 1702 assert.True(t, tr.TLSHandshake >= 0) 1703 assert.True(t, tr.ServerTime >= 0) 1704 assert.True(t, tr.ResponseTime >= 0) 1705 assert.True(t, tr.TotalTime >= 0) 1706 assert.True(t, tr.TotalTime == resp.Time()) 1707 assert.Equal(t, tr.RemoteAddr.String(), serverAddr) 1708 } 1709 1710 // for sake of hook funcs 1711 _, _ = client.R().SetTrace(true).Get("https://httpbin.org/get") 1712 } 1713 1714 func TestTraceInfoWithoutEnableTrace(t *testing.T) { 1715 ts := createGetServer(t) 1716 defer ts.Close() 1717 1718 client := dc() 1719 client.SetBaseURL(ts.URL) 1720 for _, u := range []string{"/", "/json", "/long-text", "/long-json"} { 1721 resp, err := client.R().Get(u) 1722 assert.Nil(t, err) 1723 assert.NotNil(t, resp) 1724 1725 tr := resp.Request.TraceInfo() 1726 assert.True(t, tr.DNSLookup == 0) 1727 assert.True(t, tr.ConnTime == 0) 1728 assert.True(t, tr.TLSHandshake == 0) 1729 assert.True(t, tr.ServerTime == 0) 1730 assert.True(t, tr.ResponseTime == 0) 1731 assert.True(t, tr.TotalTime == 0) 1732 } 1733 } 1734 1735 func TestTraceInfoOnTimeout(t *testing.T) { 1736 client := dc() 1737 client.SetBaseURL("http://resty-nowhere.local").SetTrace(true) 1738 1739 resp, err := client.R().Get("/") 1740 assert.NotNil(t, err) 1741 assert.NotNil(t, resp) 1742 1743 tr := resp.Request.TraceInfo() 1744 assert.True(t, tr.DNSLookup >= 0) 1745 assert.True(t, tr.ConnTime == 0) 1746 assert.True(t, tr.TLSHandshake == 0) 1747 assert.True(t, tr.TCPConnTime == 0) 1748 assert.True(t, tr.ServerTime == 0) 1749 assert.True(t, tr.ResponseTime == 0) 1750 assert.True(t, tr.TotalTime > 0) 1751 assert.True(t, tr.TotalTime == resp.Time()) 1752 } 1753 1754 func TestDebugLoggerRequestBodyTooLarge(t *testing.T) { 1755 ts := createFilePostServer(t) 1756 defer ts.Close() 1757 1758 debugBodySizeLimit := int64(512) 1759 1760 // upload an image with more than 512 bytes 1761 output := bytes.NewBufferString("") 1762 resp, err := New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R(). 1763 SetFile("file", filepath.Join(getTestDataPath(), "test-img.png")). 1764 SetHeader("Content-Type", "image/png"). 1765 Post(ts.URL + "/upload") 1766 assert.Nil(t, err) 1767 assert.NotNil(t, resp) 1768 assert.True(t, strings.Contains(output.String(), "REQUEST TOO LARGE")) 1769 1770 // upload a text file with no more than 512 bytes 1771 output = bytes.NewBufferString("") 1772 resp, err = New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R(). 1773 SetFile("file", filepath.Join(getTestDataPath(), "text-file.txt")). 1774 SetHeader("Content-Type", "text/plain"). 1775 Post(ts.URL + "/upload") 1776 assert.Nil(t, err) 1777 assert.NotNil(t, resp) 1778 assert.True(t, strings.Contains(output.String(), " THIS IS TEXT FILE FOR MULTIPART UPLOAD TEST ")) 1779 1780 formTs := createFormPostServer(t) 1781 defer formTs.Close() 1782 1783 // post form with more than 512 bytes data 1784 output = bytes.NewBufferString("") 1785 resp, err = New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R(). 1786 SetFormData(map[string]string{ 1787 "first_name": "Alex", 1788 "last_name": strings.Repeat("C", int(debugBodySizeLimit)), 1789 "zip_code": "00001", 1790 }). 1791 SetBasicAuth("myuser", "mypass"). 1792 Post(formTs.URL + "/profile") 1793 assert.Nil(t, err) 1794 assert.NotNil(t, resp) 1795 assert.True(t, strings.Contains(output.String(), "REQUEST TOO LARGE")) 1796 1797 // post form with no more than 512 bytes data 1798 output = bytes.NewBufferString("") 1799 resp, err = New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R(). 1800 SetFormData(map[string]string{ 1801 "first_name": "Alex", 1802 "last_name": "C", 1803 "zip_code": "00001", 1804 }). 1805 SetBasicAuth("myuser", "mypass"). 1806 Post(formTs.URL + "/profile") 1807 assert.Nil(t, err) 1808 assert.NotNil(t, resp) 1809 assert.True(t, strings.Contains(output.String(), "Alex")) 1810 1811 // post string with more than 512 bytes data 1812 output = bytes.NewBufferString("") 1813 resp, err = New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R(). 1814 SetBody(`{ 1815 "first_name": "Alex", 1816 "last_name": "`+strings.Repeat("C", int(debugBodySizeLimit))+`C", 1817 "zip_code": "00001"}`). 1818 SetBasicAuth("myuser", "mypass"). 1819 Post(formTs.URL + "/profile") 1820 assert.Nil(t, err) 1821 assert.NotNil(t, resp) 1822 assert.True(t, strings.Contains(output.String(), "REQUEST TOO LARGE")) 1823 1824 // post slice with more than 512 bytes data 1825 output = bytes.NewBufferString("") 1826 resp, err = New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R(). 1827 SetBody([]string{strings.Repeat("C", int(debugBodySizeLimit))}). 1828 SetBasicAuth("myuser", "mypass"). 1829 Post(formTs.URL + "/profile") 1830 assert.Nil(t, err) 1831 assert.NotNil(t, resp) 1832 assert.True(t, strings.Contains(output.String(), "REQUEST TOO LARGE")) 1833 } 1834 1835 func TestPostMapTemporaryRedirect(t *testing.T) { 1836 ts := createPostServer(t) 1837 defer ts.Close() 1838 1839 c := dc() 1840 resp, err := c.R().SetBody(map[string]string{"username": "testuser", "password": "testpass"}). 1841 Post(ts.URL + "/redirect") 1842 1843 assert.Nil(t, err) 1844 assert.NotNil(t, resp) 1845 assert.Equal(t, http.StatusOK, resp.StatusCode()) 1846 } 1847 1848 type brokenReadCloser struct{} 1849 1850 func (b brokenReadCloser) Read(_ []byte) (n int, err error) { 1851 return 0, errors.New("read error") 1852 } 1853 1854 func (b brokenReadCloser) Close() error { 1855 return nil 1856 } 1857 1858 func TestPostBodyError(t *testing.T) { 1859 ts := createPostServer(t) 1860 defer ts.Close() 1861 1862 c := dc() 1863 resp, err := c.R().SetBody(brokenReadCloser{}).Post(ts.URL + "/redirect") 1864 assert.NotNil(t, err) 1865 assert.Equal(t, "read error", err.Error()) 1866 assert.Nil(t, resp) 1867 }