1package cloudflare 2 3import ( 4 "context" 5 "fmt" 6 "io/ioutil" 7 "net/http" 8 "testing" 9 "time" 10 11 "github.com/stretchr/testify/assert" 12) 13 14func TestCustomHostname_DeleteCustomHostname(t *testing.T) { 15 setup() 16 defer teardown() 17 18 mux.HandleFunc("/zones/foo/custom_hostnames/bar", func(w http.ResponseWriter, r *http.Request) { 19 assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) 20 21 w.Header().Set("content-type", "application/json") 22 fmt.Fprintf(w, ` 23{ 24 "id": "bar" 25}`) 26 }) 27 28 err := client.DeleteCustomHostname(context.Background(), "foo", "bar") 29 30 assert.NoError(t, err) 31} 32 33func TestCustomHostname_CreateCustomHostname(t *testing.T) { 34 setup() 35 defer teardown() 36 37 mux.HandleFunc("/zones/foo/custom_hostnames", func(w http.ResponseWriter, r *http.Request) { 38 assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) 39 40 w.Header().Set("content-type", "application/json") 41 w.WriteHeader(http.StatusCreated) 42 fmt.Fprintf(w, ` 43{ 44 "success": true, 45 "errors": [], 46 "messages": [], 47 "result": { 48 "id": "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 49 "hostname": "app.example.com", 50 "custom_origin_server": "example.app.com", 51 "ssl": { 52 "status": "pending_validation", 53 "method": "cname", 54 "type": "dv", 55 "cname_target": "dcv.digicert.com", 56 "cname": "810b7d5f01154524b961ba0cd578acc2.app.example.com", 57 "settings": { 58 "http2": "on" 59 } 60 }, 61 "status": "pending", 62 "verification_errors": [ 63 "None of the A or AAAA records are owned by this account and the pre-generated ownership verification token was not found." 64 ], 65 "ownership_verification": { 66 "type": "txt", 67 "name": "_cf-custom-hostname.app.example.com", 68 "value": "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0" 69 }, 70 "ownership_verification_http": { 71 "http_url": "http://app.example.com/.well-known/cf-custom-hostname-challenge/37c82d20-99fb-490e-ba0a-489fa483b776", 72 "http_body": "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0" 73 }, 74 "created_at": "2020-02-06T18:11:23.531995Z" 75 } 76}`) 77 }) 78 79 response, err := client.CreateCustomHostname(context.Background(), "foo", CustomHostname{Hostname: "app.example.com", SSL: &CustomHostnameSSL{Method: "cname", Type: "dv"}}) 80 81 createdAt, _ := time.Parse(time.RFC3339, "2020-02-06T18:11:23.531995Z") 82 83 want := &CustomHostnameResponse{ 84 Result: CustomHostname{ 85 ID: "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 86 Hostname: "app.example.com", 87 CustomOriginServer: "example.app.com", 88 SSL: &CustomHostnameSSL{ 89 Type: "dv", 90 Method: "cname", 91 Status: "pending_validation", 92 CnameTarget: "dcv.digicert.com", 93 CnameName: "810b7d5f01154524b961ba0cd578acc2.app.example.com", 94 Settings: CustomHostnameSSLSettings{ 95 HTTP2: "on", 96 }, 97 }, 98 Status: "pending", 99 VerificationErrors: []string{"None of the A or AAAA records are owned by this account and the pre-generated ownership verification token was not found."}, 100 OwnershipVerification: CustomHostnameOwnershipVerification{ 101 Type: "txt", 102 Name: "_cf-custom-hostname.app.example.com", 103 Value: "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0", 104 }, 105 OwnershipVerificationHTTP: CustomHostnameOwnershipVerificationHTTP{ 106 HTTPUrl: "http://app.example.com/.well-known/cf-custom-hostname-challenge/37c82d20-99fb-490e-ba0a-489fa483b776", 107 HTTPBody: "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0", 108 }, 109 CreatedAt: &createdAt, 110 }, 111 Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, 112 } 113 114 if assert.NoError(t, err) { 115 assert.Equal(t, want, response) 116 } 117} 118 119func TestCustomHostname_CreateCustomHostname_MethodTxt(t *testing.T) { 120 setup() 121 defer teardown() 122 123 mux.HandleFunc("/zones/foo/custom_hostnames", func(w http.ResponseWriter, r *http.Request) { 124 assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) 125 126 w.Header().Set("content-type", "application/json") 127 w.WriteHeader(http.StatusCreated) 128 fmt.Fprintf(w, ` 129{ 130 "success": true, 131 "errors": [], 132 "messages": [], 133 "result": { 134 "id": "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 135 "hostname": "app.example.com", 136 "custom_origin_server": "example.app.com", 137 "ssl": { 138 "status": "pending_validation", 139 "method": "txt", 140 "type": "dv", 141 "txt_name": "app.example.com", 142 "txt_value": "ca3-f8db94da174g4c409b17fcaa5470deb2", 143 "settings": { 144 "http2": "on" 145 } 146 }, 147 "status": "pending", 148 "verification_errors": [ 149 "None of the A or AAAA records are owned by this account and the pre-generated ownership verification token was not found." 150 ], 151 "ownership_verification": { 152 "type": "txt", 153 "name": "_cf-custom-hostname.app.example.com", 154 "value": "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0" 155 }, 156 "ownership_verification_http": { 157 "http_url": "http://app.example.com/.well-known/cf-custom-hostname-challenge/37c82d20-99fb-490e-ba0a-489fa483b776", 158 "http_body": "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0" 159 }, 160 "created_at": "2020-02-06T18:11:23.531995Z" 161 } 162}`) 163 }) 164 165 response, err := client.CreateCustomHostname(context.Background(), "foo", CustomHostname{Hostname: "app.example.com", SSL: &CustomHostnameSSL{Method: "txt", Type: "dv"}}) 166 167 createdAt, _ := time.Parse(time.RFC3339, "2020-02-06T18:11:23.531995Z") 168 169 want := &CustomHostnameResponse{ 170 Result: CustomHostname{ 171 ID: "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 172 Hostname: "app.example.com", 173 CustomOriginServer: "example.app.com", 174 SSL: &CustomHostnameSSL{ 175 Type: "dv", 176 Method: "txt", 177 Status: "pending_validation", 178 TxtName: "app.example.com", 179 TxtValue: "ca3-f8db94da174g4c409b17fcaa5470deb2", 180 Settings: CustomHostnameSSLSettings{ 181 HTTP2: "on", 182 }, 183 }, 184 Status: "pending", 185 VerificationErrors: []string{"None of the A or AAAA records are owned by this account and the pre-generated ownership verification token was not found."}, 186 OwnershipVerification: CustomHostnameOwnershipVerification{ 187 Type: "txt", 188 Name: "_cf-custom-hostname.app.example.com", 189 Value: "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0", 190 }, 191 OwnershipVerificationHTTP: CustomHostnameOwnershipVerificationHTTP{ 192 HTTPUrl: "http://app.example.com/.well-known/cf-custom-hostname-challenge/37c82d20-99fb-490e-ba0a-489fa483b776", 193 HTTPBody: "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0", 194 }, 195 CreatedAt: &createdAt, 196 }, 197 Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, 198 } 199 200 if assert.NoError(t, err) { 201 assert.Equal(t, want, response) 202 } 203} 204 205func TestCustomHostname_CreateCustomHostname_CustomOrigin(t *testing.T) { 206 setup() 207 defer teardown() 208 209 mux.HandleFunc("/zones/foo/custom_hostnames", func(w http.ResponseWriter, r *http.Request) { 210 assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) 211 212 w.Header().Set("content-type", "application/json") 213 w.WriteHeader(http.StatusCreated) 214 fmt.Fprintf(w, ` 215{ 216 "success": true, 217 "errors": [], 218 "messages": [], 219 "result": { 220 "id": "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 221 "hostname": "app.example.com", 222 "custom_origin_server": "example.app.com", 223 "ssl": { 224 "status": "pending_validation", 225 "method": "cname", 226 "type": "dv", 227 "cname_target": "dcv.digicert.com", 228 "cname": "810b7d5f01154524b961ba0cd578acc2.app.example.com", 229 "settings": { 230 "http2": "on" 231 } 232 } 233 } 234}`) 235 }) 236 237 response, err := client.CreateCustomHostname(context.Background(), "foo", CustomHostname{Hostname: "app.example.com", CustomOriginServer: "example.app.com", SSL: &CustomHostnameSSL{Method: "cname", Type: "dv"}}) 238 239 want := &CustomHostnameResponse{ 240 Result: CustomHostname{ 241 ID: "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 242 Hostname: "app.example.com", 243 CustomOriginServer: "example.app.com", 244 SSL: &CustomHostnameSSL{ 245 Type: "dv", 246 Method: "cname", 247 Status: "pending_validation", 248 CnameTarget: "dcv.digicert.com", 249 CnameName: "810b7d5f01154524b961ba0cd578acc2.app.example.com", 250 Settings: CustomHostnameSSLSettings{ 251 HTTP2: "on", 252 }, 253 }, 254 }, 255 Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, 256 } 257 258 if assert.NoError(t, err) { 259 assert.Equal(t, want, response) 260 } 261} 262 263func TestCustomHostname_CreateCustomHostname_No_SSL(t *testing.T) { 264 setup() 265 defer teardown() 266 267 mux.HandleFunc("/zones/foo/custom_hostnames", func(w http.ResponseWriter, r *http.Request) { 268 assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) 269 270 w.Header().Set("content-type", "application/json") 271 w.WriteHeader(http.StatusCreated) 272 fmt.Fprintf(w, ` 273{ 274 "success": true, 275 "errors": [], 276 "messages": [], 277 "result": { 278 "id": "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 279 "hostname": "app.example.com", 280 "custom_origin_server": "example.app.com", 281 "status": "pending", 282 "verification_errors": [ 283 "None of the A or AAAA records are owned by this account and the pre-generated ownership verification token was not found." 284 ], 285 "ownership_verification": { 286 "type": "txt", 287 "name": "_cf-custom-hostname.app.example.com", 288 "value": "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0" 289 }, 290 "ownership_verification_http": { 291 "http_url": "http://app.example.com/.well-known/cf-custom-hostname-challenge/37c82d20-99fb-490e-ba0a-489fa483b776", 292 "http_body": "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0" 293 }, 294 "created_at": "2020-02-06T18:11:23.531995Z" 295 } 296}`) 297 }) 298 299 response, err := client.CreateCustomHostname(context.Background(), "foo", CustomHostname{Hostname: "app.example.com"}) 300 301 createdAt, _ := time.Parse(time.RFC3339, "2020-02-06T18:11:23.531995Z") 302 303 want := &CustomHostnameResponse{ 304 Result: CustomHostname{ 305 ID: "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 306 Hostname: "app.example.com", 307 CustomOriginServer: "example.app.com", 308 Status: "pending", 309 VerificationErrors: []string{"None of the A or AAAA records are owned by this account and the pre-generated ownership verification token was not found."}, 310 OwnershipVerification: CustomHostnameOwnershipVerification{ 311 Type: "txt", 312 Name: "_cf-custom-hostname.app.example.com", 313 Value: "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0", 314 }, 315 OwnershipVerificationHTTP: CustomHostnameOwnershipVerificationHTTP{ 316 HTTPUrl: "http://app.example.com/.well-known/cf-custom-hostname-challenge/37c82d20-99fb-490e-ba0a-489fa483b776", 317 HTTPBody: "38ddbedc-6cc3-4a4c-af67-9c5b02344ce0", 318 }, 319 CreatedAt: &createdAt, 320 }, 321 Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, 322 } 323 324 if assert.NoError(t, err) { 325 assert.Equal(t, want, response) 326 } 327} 328 329func TestCustomHostname_CustomHostnames(t *testing.T) { 330 setup() 331 defer teardown() 332 333 mux.HandleFunc("/zones/foo/custom_hostnames", func(w http.ResponseWriter, r *http.Request) { 334 assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) 335 336 w.Header().Set("content-type", "application/json") 337 fmt.Fprintf(w, `{ 338 "success": true, 339 "result": [ 340 { 341 "id": "custom_host_1", 342 "hostname": "custom.host.one", 343 "ssl": { 344 "id": "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 345 "type": "dv", 346 "method": "cname", 347 "status": "pending_validation", 348 "cname_target": "dcv.digicert.com", 349 "cname": "810b7d5f01154524b961ba0cd578acc2.app.example.com", 350 "issuer": "DigiCertInc", 351 "serial_number": "6743787633689793699141714808227354901", 352 "http_url": "http://app.example.com/.well-known/pki-validation/ca3-da12a1c25e7b48cf80408c6c1763b8a2.txt", 353 "http_body": "ca3-574923932a82475cb8592200f1a2a23d" 354 }, 355 "custom_metadata": { 356 "a_random_field": "random field value" 357 }, 358 "status": "pending", 359 "verification_errors": [ 360 "None of the A or AAAA records are owned by this account and the pre-generated ownership verification token was not found." 361 ], 362 "ownership_verification": { 363 "type": "txt", 364 "name": "_cf-custom-hostname.app.example.com", 365 "value": "5cc07c04-ea62-4a5a-95f0-419334a875a4" 366 } 367 } 368 ], 369 "result_info": { 370 "page": 1, 371 "per_page": 20, 372 "count": 5, 373 "total_count": 5 374 } 375}`) 376 }) 377 378 customHostnames, _, err := client.CustomHostnames(context.Background(), "foo", 1, CustomHostname{}) 379 380 want := []CustomHostname{ 381 { 382 ID: "custom_host_1", 383 Hostname: "custom.host.one", 384 SSL: &CustomHostnameSSL{ 385 ID: "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 386 Type: "dv", 387 Method: "cname", 388 Status: "pending_validation", 389 CnameTarget: "dcv.digicert.com", 390 CnameName: "810b7d5f01154524b961ba0cd578acc2.app.example.com", 391 Issuer: "DigiCertInc", 392 SerialNumber: "6743787633689793699141714808227354901", 393 HTTPUrl: "http://app.example.com/.well-known/pki-validation/ca3-da12a1c25e7b48cf80408c6c1763b8a2.txt", 394 HTTPBody: "ca3-574923932a82475cb8592200f1a2a23d", 395 }, 396 CustomMetadata: CustomMetadata{"a_random_field": "random field value"}, 397 Status: PENDING, 398 VerificationErrors: []string{"None of the A or AAAA records are owned " + 399 "by this account and the pre-generated ownership verification token was not found."}, 400 OwnershipVerification: CustomHostnameOwnershipVerification{ 401 Type: "txt", 402 Name: "_cf-custom-hostname.app.example.com", 403 Value: "5cc07c04-ea62-4a5a-95f0-419334a875a4", 404 }, 405 }, 406 } 407 408 if assert.NoError(t, err) { 409 assert.Equal(t, want, customHostnames) 410 } 411} 412 413func TestCustomHostname_CustomHostname(t *testing.T) { 414 setup() 415 defer teardown() 416 417 mux.HandleFunc("/zones/foo/custom_hostnames/bar", func(w http.ResponseWriter, r *http.Request) { 418 assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) 419 420 w.Header().Set("content-type", "application/json") 421 fmt.Fprintf(w, `{ 422"success": true, 423"result": { 424 "id": "bar", 425 "hostname": "foo.bar.com", 426 "ssl": { 427 "id": "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 428 "type": "dv", 429 "method": "http", 430 "status": "active", 431 "issuer": "DigiCertInc", 432 "serial_number": "6743787633689793699141714808227354901", 433 "settings": { 434 "ciphers": ["ECDHE-RSA-AES128-GCM-SHA256","AES128-SHA"], 435 "http2": "on", 436 "min_tls_version": "1.2" 437 } 438 }, 439 "custom_metadata": { 440 "origin": "a.custom.origin" 441 }, 442 "status": "pending", 443 "verification_errors": [ 444 "None of the A or AAAA records are owned by this account and the pre-generated ownership verification token was not found." 445 ], 446 "ownership_verification": { 447 "type": "txt", 448 "name": "_cf-custom-hostname.app.example.com", 449 "value": "5cc07c04-ea62-4a5a-95f0-419334a875a4" 450 } 451 } 452}`) 453 }) 454 455 customHostname, err := client.CustomHostname(context.Background(), "foo", "bar") 456 457 want := CustomHostname{ 458 ID: "bar", 459 Hostname: "foo.bar.com", 460 SSL: &CustomHostnameSSL{ 461 ID: "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 462 Status: "active", 463 Method: "http", 464 Type: "dv", 465 Issuer: "DigiCertInc", 466 SerialNumber: "6743787633689793699141714808227354901", 467 Settings: CustomHostnameSSLSettings{ 468 HTTP2: "on", 469 MinTLSVersion: "1.2", 470 Ciphers: []string{"ECDHE-RSA-AES128-GCM-SHA256", "AES128-SHA"}, 471 }, 472 }, 473 CustomMetadata: CustomMetadata{"origin": "a.custom.origin"}, 474 Status: PENDING, 475 VerificationErrors: []string{"None of the A or AAAA records are owned " + 476 "by this account and the pre-generated ownership verification token was not found."}, 477 OwnershipVerification: CustomHostnameOwnershipVerification{ 478 Type: "txt", 479 Name: "_cf-custom-hostname.app.example.com", 480 Value: "5cc07c04-ea62-4a5a-95f0-419334a875a4", 481 }, 482 } 483 484 if assert.NoError(t, err) { 485 assert.Equal(t, want, customHostname) 486 } 487} 488 489func TestCustomHostname_CustomHostname_WithSSLError(t *testing.T) { 490 setup() 491 defer teardown() 492 493 mux.HandleFunc("/zones/foo/custom_hostnames/bar", func(w http.ResponseWriter, r *http.Request) { 494 assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) 495 496 w.Header().Set("content-type", "application/json") 497 fmt.Fprintf(w, `{ 498"success": true, 499"result": { 500 "id": "bar", 501 "hostname": "example.com", 502 "ssl": { 503 "type": "dv", 504 "method": "cname", 505 "status": "pending_validation", 506 "cname_target": "dcv.digicert.com", 507 "cname": "810b7d5f01154524b961ba0cd578acc2.example.com", 508 "validation_errors": [{ 509 "message": "SERVFAIL looking up CAA for example.com" 510 }] 511 }, 512 "status": "pending", 513 "verification_errors": [ 514 "None of the A or AAAA records are owned by this account and the pre-generated ownership verification token was not found." 515 ], 516 "ownership_verification_http": { 517 "http_url": "http://example.com/.well-known/cf-custom-hostname-challenge/0d89c70d-ad9f-4843-b99f-6cc0252067e9", 518 "http_body": "5cc07c04-ea62-4a5a-95f0-419334a875a4" 519 } 520} 521}`) 522 }) 523 524 customHostname, err := client.CustomHostname(context.Background(), "foo", "bar") 525 526 want := CustomHostname{ 527 ID: "bar", 528 Hostname: "example.com", 529 SSL: &CustomHostnameSSL{ 530 Type: "dv", 531 Method: "cname", 532 Status: "pending_validation", 533 CnameName: "810b7d5f01154524b961ba0cd578acc2.example.com", 534 CnameTarget: "dcv.digicert.com", 535 ValidationErrors: []CustomHostnameSSLValidationErrors{ 536 { 537 Message: "SERVFAIL looking up CAA for example.com", 538 }, 539 }, 540 }, 541 Status: PENDING, 542 VerificationErrors: []string{"None of the A or AAAA records are owned " + 543 "by this account and the pre-generated ownership verification token was not found."}, 544 OwnershipVerificationHTTP: CustomHostnameOwnershipVerificationHTTP{ 545 HTTPBody: "5cc07c04-ea62-4a5a-95f0-419334a875a4", 546 HTTPUrl: "http://example.com/.well-known/cf-custom-hostname-challenge/0d89c70d-ad9f-4843-b99f-6cc0252067e9", 547 }, 548 } 549 550 if assert.NoError(t, err) { 551 assert.Equal(t, want, customHostname) 552 } 553} 554 555func TestCustomHostname_UpdateCustomHostnameSSL(t *testing.T) { 556 setup() 557 defer teardown() 558 559 mux.HandleFunc("/zones/foo/custom_hostnames/0d89c70d-ad9f-4843-b99f-6cc0252067e9", func(w http.ResponseWriter, r *http.Request) { 560 assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method) 561 562 w.Header().Set("content-type", "application/json") 563 w.WriteHeader(http.StatusCreated) 564 fmt.Fprintf(w, ` 565{ 566 "success": true, 567 "errors": [], 568 "messages": [], 569 "result": { 570 "id": "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 571 "hostname": "app.example.com", 572 "custom_origin_server": "example.app.com", 573 "ssl": { 574 "status": "pending_validation", 575 "method": "cname", 576 "type": "dv", 577 "cname_target": "dcv.digicert.com", 578 "cname": "810b7d5f01154524b961ba0cd578acc2.app.example.com", 579 "settings": { 580 "http2": "off", 581 "tls_1_3": "on" 582 } 583 } 584 } 585}`) 586 }) 587 588 response, err := client.UpdateCustomHostnameSSL(context.Background(), "foo", "0d89c70d-ad9f-4843-b99f-6cc0252067e9", &CustomHostnameSSL{Method: "cname", Type: "dv", Settings: CustomHostnameSSLSettings{HTTP2: "off", TLS13: "on"}}) 589 590 want := &CustomHostnameResponse{ 591 Result: CustomHostname{ 592 ID: "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 593 Hostname: "app.example.com", 594 CustomOriginServer: "example.app.com", 595 SSL: &CustomHostnameSSL{ 596 Type: "dv", 597 Method: "cname", 598 Status: "pending_validation", 599 CnameTarget: "dcv.digicert.com", 600 CnameName: "810b7d5f01154524b961ba0cd578acc2.app.example.com", 601 Settings: CustomHostnameSSLSettings{ 602 HTTP2: "off", 603 TLS13: "on", 604 }, 605 }, 606 }, 607 Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, 608 } 609 610 if assert.NoError(t, err) { 611 assert.Equal(t, want, response) 612 } 613} 614 615func TestCustomHostname_UpdateCustomHostname(t *testing.T) { 616 setup() 617 defer teardown() 618 619 mux.HandleFunc("/zones/foo/custom_hostnames/0d89c70d-ad9f-4843-b99f-6cc0252067e9", func(w http.ResponseWriter, r *http.Request) { 620 assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method) 621 622 defer r.Body.Close() 623 reqBody, err := ioutil.ReadAll(r.Body) 624 assert.NoError(t, err, "Reading request body") 625 assert.JSONEq(t, ` 626{ 627 "hostname": "app.example.com", 628 "custom_origin_server": "example.app.com", 629 "ssl": { 630 "method": "cname", 631 "type": "dv", 632 "wildcard": false, 633 "settings": {} 634 }, 635 "ownership_verification": {}, 636 "ownership_verification_http": {} 637}`, string(reqBody), "Unexpected request body") 638 639 w.Header().Set("content-type", "application/json") 640 w.WriteHeader(http.StatusCreated) 641 fmt.Fprintf(w, ` 642{ 643 "success": true, 644 "errors": [], 645 "messages": [], 646 "result": { 647 "id": "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 648 "hostname": "app.example.com", 649 "custom_origin_server": "example.app.com", 650 "ssl": { 651 "status": "pending_validation", 652 "method": "cname", 653 "type": "dv", 654 "cname_target": "dcv.digicert.com", 655 "cname": "810b7d5f01154524b961ba0cd578acc2.app.example.com", 656 "settings": { 657 "http2": "off", 658 "tls_1_3": "on" 659 } 660 } 661 } 662}`) 663 }) 664 665 wildcard := false 666 response, err := client.UpdateCustomHostname(context.Background(), "foo", "0d89c70d-ad9f-4843-b99f-6cc0252067e9", CustomHostname{Hostname: "app.example.com", CustomOriginServer: "example.app.com", SSL: &CustomHostnameSSL{Method: "cname", Type: "dv", Wildcard: &wildcard}}) 667 668 want := &CustomHostnameResponse{ 669 Result: CustomHostname{ 670 ID: "0d89c70d-ad9f-4843-b99f-6cc0252067e9", 671 Hostname: "app.example.com", 672 CustomOriginServer: "example.app.com", 673 SSL: &CustomHostnameSSL{ 674 Type: "dv", 675 Method: "cname", 676 Status: "pending_validation", 677 CnameTarget: "dcv.digicert.com", 678 CnameName: "810b7d5f01154524b961ba0cd578acc2.app.example.com", 679 Settings: CustomHostnameSSLSettings{ 680 HTTP2: "off", 681 TLS13: "on", 682 }, 683 }, 684 }, 685 Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, 686 } 687 688 if assert.NoError(t, err) { 689 assert.Equal(t, want, response) 690 } 691} 692 693func TestCustomHostname_CustomHostnameFallbackOrigin(t *testing.T) { 694 setup() 695 defer teardown() 696 697 mux.HandleFunc("/zones/foo/custom_hostnames/fallback_origin", func(w http.ResponseWriter, r *http.Request) { 698 assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) 699 700 w.Header().Set("content-type", "application/json") 701 fmt.Fprintf(w, `{ 702 "success": true, 703 "errors": [], 704 "messages": [], 705 "result": { 706 "origin": "fallback.example.com", 707 "status": "pending_deployment", 708 "errors": [ 709 "DNS records are not setup correctly. Origin should be a proxied A/AAAA/CNAME dns record" 710 ], 711 "created_at": "2019-10-28T18:11:23.37411Z", 712 "updated_at": "2020-03-16T18:11:23.531995Z" 713 } 714}`) 715 }) 716 717 customHostnameFallbackOrigin, err := client.CustomHostnameFallbackOrigin(context.Background(), "foo") 718 719 want := CustomHostnameFallbackOrigin{ 720 Origin: "fallback.example.com", 721 Status: "pending_deployment", 722 Errors: []string{"DNS records are not setup correctly. Origin should be a proxied A/AAAA/CNAME dns record"}, 723 } 724 725 if assert.NoError(t, err) { 726 assert.Equal(t, want, customHostnameFallbackOrigin) 727 } 728} 729 730func TestCustomHostname_DeleteCustomHostnameFallbackOrigin(t *testing.T) { 731 setup() 732 defer teardown() 733 734 mux.HandleFunc("/zones/foo/custom_hostnames/fallback_origin", func(w http.ResponseWriter, r *http.Request) { 735 assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) 736 737 w.Header().Set("content-type", "application/json") 738 fmt.Fprintf(w, ` 739{ 740 "id": "bar" 741}`) 742 }) 743 744 err := client.DeleteCustomHostnameFallbackOrigin(context.Background(), "foo") 745 746 assert.NoError(t, err) 747} 748 749func TestCustomHostname_UpdateCustomHostnameFallbackOrigin(t *testing.T) { 750 setup() 751 defer teardown() 752 753 mux.HandleFunc("/zones/foo/custom_hostnames/fallback_origin", func(w http.ResponseWriter, r *http.Request) { 754 assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) 755 756 w.Header().Set("content-type", "application/json") 757 w.WriteHeader(http.StatusCreated) 758 fmt.Fprintf(w, ` 759{ 760 "success": true, 761 "errors": [], 762 "messages": [], 763 "result": { 764 "origin": "fallback.example.com", 765 "status": "pending_deployment", 766 "errors": [ 767 "DNS records are not setup correctly. Origin should be a proxied A/AAAA/CNAME dns record" 768 ], 769 "created_at": "2019-10-28T18:11:23.37411Z", 770 "updated_at": "2020-03-16T18:11:23.531995Z" 771 } 772}`) 773 }) 774 775 response, err := client.UpdateCustomHostnameFallbackOrigin(context.Background(), "foo", CustomHostnameFallbackOrigin{Origin: "fallback.example.com"}) 776 777 want := &CustomHostnameFallbackOriginResponse{ 778 Result: CustomHostnameFallbackOrigin{ 779 Origin: "fallback.example.com", 780 Status: "pending_deployment", 781 Errors: []string{"DNS records are not setup correctly. Origin should be a proxied A/AAAA/CNAME dns record"}, 782 }, 783 Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, 784 } 785 786 if assert.NoError(t, err) { 787 assert.Equal(t, want, response) 788 } 789} 790 791func TestCustomHostname_CreateCustomHostnameCustomCertificateAuthority(t *testing.T) { 792 setup() 793 defer teardown() 794 795 mux.HandleFunc("/zones/foo/custom_hostnames", func(w http.ResponseWriter, r *http.Request) { 796 assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) 797 798 w.Header().Set("content-type", "application/json") 799 w.WriteHeader(http.StatusCreated) 800 fmt.Fprintf(w, ` 801{ 802 "result": { 803 "id": "614b3124-cd57-42f0-8307-000000000000", 804 "hostname": "app.example.com", 805 "ssl": { 806 "id": "d9ae4881-34d2-4820-8e28-000000000000", 807 "type": "dv", 808 "method": "http", 809 "status": "initializing", 810 "settings": { 811 "min_tls_version": "1.2" 812 }, 813 "wildcard": false, 814 "certificate_authority": "lets_encrypt" 815 }, 816 "custom_origin_server": "origin.example.com", 817 "created_at": "2020-06-30T21:37:36.563495Z" 818 }, 819 "success": true, 820 "errors": [], 821 "messages": [] 822}`) 823 }) 824 825 response, err := client.CreateCustomHostname(context.Background(), "foo", CustomHostname{Hostname: "app.example.com", SSL: &CustomHostnameSSL{Method: "cname", Type: "dv", CertificateAuthority: "lets_encrypt"}}) 826 827 createdAt, _ := time.Parse(time.RFC3339, "2020-06-30T21:37:36.563495Z") 828 829 wildcard := false 830 want := &CustomHostnameResponse{ 831 Result: CustomHostname{ 832 ID: "614b3124-cd57-42f0-8307-000000000000", 833 Hostname: "app.example.com", 834 CustomOriginServer: "origin.example.com", 835 SSL: &CustomHostnameSSL{ 836 ID: "d9ae4881-34d2-4820-8e28-000000000000", 837 Type: "dv", 838 Method: "http", 839 Status: "initializing", 840 Settings: CustomHostnameSSLSettings{ 841 MinTLSVersion: "1.2", 842 }, 843 Wildcard: &wildcard, 844 CertificateAuthority: "lets_encrypt", 845 }, 846 CreatedAt: &createdAt, 847 }, 848 Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, 849 } 850 851 if assert.NoError(t, err) { 852 assert.Equal(t, want, response) 853 } 854} 855