94 lines
3.5 KiB
Go
94 lines
3.5 KiB
Go
package cloudflare
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestClientCreatesTunnelCNAME(t *testing.T) {
|
|
requests := 0
|
|
server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
|
requests++
|
|
if request.Header.Get("Authorization") != "Bearer test-api-token" {
|
|
t.Error("Cloudflare request did not use the API token header")
|
|
writer.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
switch request.Method + " " + request.URL.Path {
|
|
case "GET /zones/zone-id/dns_records":
|
|
if request.URL.Query().Get("type") != "CNAME" || request.URL.Query().Get("name") != "app.example.test" {
|
|
t.Error("DNS lookup was invalid")
|
|
}
|
|
_ = json.NewEncoder(writer).Encode(map[string]any{"success": true, "result": []any{}})
|
|
case "POST /zones/zone-id/dns_records":
|
|
var body map[string]any
|
|
if err := json.NewDecoder(request.Body).Decode(&body); err != nil || body["content"] != "tunnel-id.cfargotunnel.com" || body["proxied"] != true {
|
|
t.Error("DNS create request was invalid")
|
|
}
|
|
_ = json.NewEncoder(writer).Encode(map[string]any{"success": true, "result": map[string]string{"id": "record-id"}})
|
|
default:
|
|
t.Errorf("unexpected request %s %s", request.Method, request.URL.Path)
|
|
writer.WriteHeader(http.StatusMethodNotAllowed)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient("test-api-token")
|
|
client.baseURL = server.URL
|
|
client.httpClient = server.Client()
|
|
if err := client.EnsureCNAME(context.Background(), "zone-id", "app.example.test", "tunnel-id"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if requests != 2 {
|
|
t.Fatalf("expected two Cloudflare requests, got %d", requests)
|
|
}
|
|
}
|
|
|
|
func TestClientFailureDoesNotRevealToken(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) {
|
|
writer.WriteHeader(http.StatusInternalServerError)
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient("test-api-token")
|
|
client.baseURL = server.URL
|
|
client.httpClient = server.Client()
|
|
err := client.EnsureCNAME(context.Background(), "zone-id", "app.example.test", "tunnel-id")
|
|
if err == nil || strings.Contains(err.Error(), "test-api-token") {
|
|
t.Fatal("Cloudflare API failure exposed the token")
|
|
}
|
|
}
|
|
|
|
func TestClientDeletesOnlyMatchingTunnelCNAME(t *testing.T) {
|
|
deleted := false
|
|
server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
|
if request.Header.Get("Authorization") != "Bearer test-api-token" {
|
|
t.Error("Cloudflare request did not use the API token header")
|
|
writer.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
switch request.Method + " " + request.URL.Path {
|
|
case "GET /zones/zone-id/dns_records":
|
|
_ = json.NewEncoder(writer).Encode(map[string]any{"success": true, "result": []map[string]any{{"id": "record-id", "name": "app.example.test", "content": "tunnel-id.cfargotunnel.com", "proxied": true}}})
|
|
case "DELETE /zones/zone-id/dns_records/record-id":
|
|
deleted = true
|
|
_ = json.NewEncoder(writer).Encode(map[string]any{"success": true, "result": map[string]string{"id": "record-id"}})
|
|
default:
|
|
t.Errorf("unexpected request %s %s", request.Method, request.URL.Path)
|
|
writer.WriteHeader(http.StatusMethodNotAllowed)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient("test-api-token")
|
|
client.baseURL = server.URL
|
|
client.httpClient = server.Client()
|
|
if err := client.DeleteCNAME(context.Background(), "zone-id", "app.example.test", "tunnel-id"); err != nil || !deleted {
|
|
t.Fatal("matching managed CNAME was not deleted")
|
|
}
|
|
}
|