@@ -3,6 +3,7 @@ package speakeasy_test
33import (
44 "bytes"
55 "context"
6+ "crypto/tls"
67 "encoding/json"
78 "io/ioutil"
89 "log"
@@ -16,6 +17,7 @@ import (
1617 "testing"
1718 "time"
1819
20+ "github.com/chromedp/cdproto/har"
1921 "github.com/gin-gonic/gin"
2022 "github.com/go-chi/chi/v5"
2123 "github.com/gorilla/mux"
@@ -269,6 +271,127 @@ func TestSpeakeasy_Middleware_Capture_Success(t *testing.T) {
269271 }
270272}
271273
274+ func TestSpeakeasy_Middleware_URL_Resolve_Success (t * testing.T ) {
275+ type args struct {
276+ url string
277+ headers map [string ]string
278+ host string
279+ https bool
280+ }
281+ tests := []struct {
282+ name string
283+ args args
284+ wantResolvedURL string
285+ }{
286+ {
287+ name : "successfully resolves relative URL" ,
288+ args : args {
289+ url : "/v1/users" ,
290+ host : "localhost:8080" ,
291+ },
292+ wantResolvedURL : "http://localhost:8080/v1/users" ,
293+ },
294+ {
295+ name : "successfully resolves relative HTTPS URL" ,
296+ args : args {
297+ url : "/v1/users" ,
298+ host : "localhost:8080" ,
299+ https : true ,
300+ },
301+ wantResolvedURL : "https://localhost:8080/v1/users" ,
302+ },
303+ {
304+ name : "successfully resolves absolute URL" ,
305+ args : args {
306+ url : "https://localhost:8080/v1/users" ,
307+ },
308+ wantResolvedURL : "https://localhost:8080/v1/users" ,
309+ },
310+ {
311+ name : "successfully resolves relative URL behind proxy" ,
312+ args : args {
313+ url : "/v1/users" ,
314+ host : "localhost:8080" ,
315+ headers : map [string ]string {
316+ "X-Forwarded-Host" : "dev.speakeasyapi.dev" ,
317+ "X-Forwarded-Proto" : "https" ,
318+ },
319+ },
320+ wantResolvedURL : "https://dev.speakeasyapi.dev/v1/users" ,
321+ },
322+ {
323+ name : "successfully resolves absolute URL behind proxy" ,
324+ args : args {
325+ url : "http://10.0.0.1:8080/v1/users" ,
326+ headers : map [string ]string {
327+ "X-Forwarded-Host" : "dev.speakeasyapi.dev" ,
328+ "X-Forwarded-Proto" : "https" ,
329+ },
330+ },
331+ wantResolvedURL : "https://dev.speakeasyapi.dev/v1/users" ,
332+ },
333+ }
334+ for _ , tt := range tests {
335+ t .Run (tt .name , func (t * testing.T ) {
336+ captured := false
337+ handled := false
338+
339+ speakeasy .ExportSetTimeNow (time .Date (2020 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC ))
340+ speakeasy .ExportSetTimeSince (1 * time .Millisecond )
341+
342+ wg := & sync.WaitGroup {}
343+ wg .Add (1 )
344+
345+ sdkInstance := speakeasy .New (speakeasy.Config {
346+ APIKey : testAPIKey ,
347+ ApiID : testApiID ,
348+ VersionID : testVersionID ,
349+ GRPCDialer : dialer (func (ctx context.Context , req * ingest.IngestRequest ) {
350+ var h har.HAR
351+
352+ err := json .Unmarshal ([]byte (req .GetHar ()), & h )
353+ require .NoError (t , err )
354+
355+ assert .Equal (t , tt .wantResolvedURL , h .Log .Entries [0 ].Request .URL )
356+ captured = true
357+ wg .Done ()
358+ }),
359+ })
360+
361+ r := mux .NewRouter ()
362+ r .Use (sdkInstance .Middleware )
363+
364+ r .Methods (http .MethodGet ).Path ("/v1/users" ).HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
365+ w .WriteHeader (http .StatusOK )
366+ handled = true
367+ })
368+
369+ w := httptest .NewRecorder ()
370+
371+ req , err := http .NewRequest (http .MethodGet , tt .args .url , nil )
372+ assert .NoError (t , err )
373+
374+ if tt .args .host != "" {
375+ req .Host = tt .args .host
376+ }
377+ for k , v := range tt .args .headers {
378+ req .Header .Add (k , v )
379+ }
380+ if tt .args .https {
381+ req .TLS = & tls.ConnectionState {}
382+ }
383+
384+ r .ServeHTTP (w , req )
385+
386+ wg .Wait ()
387+
388+ assert .True (t , handled , "middleware did not call handler" )
389+ assert .True (t , captured , "middleware did not capture request" )
390+ assert .Equal (t , http .StatusOK , w .Code )
391+ })
392+ }
393+ }
394+
272395func TestSpeakeasy_Middleware_GorillaMux_PathHint_Success (t * testing.T ) {
273396 type args struct {
274397 path string
0 commit comments