@@ -321,203 +321,8 @@ func createFeatureChecker(enabledFeatures []string) inventory.FeatureFlagChecker
321321 for _ , f := range enabledFeatures {
322322 featureSet [f ] = true
323323 }
324- << << << < HEAD
325324 return func (_ context.Context , flagName string ) (bool , error ) {
326325 return featureSet [flagName ], nil
327- == == == =
328-
329- gqlURL , err := url .Parse ("https://api.github.com/graphql" )
330- if err != nil {
331- return apiHost {}, fmt .Errorf ("failed to parse dotcom GraphQL URL: %w" , err )
332- }
333-
334- uploadURL , err := url .Parse ("https://uploads.github.com" )
335- if err != nil {
336- return apiHost {}, fmt .Errorf ("failed to parse dotcom Upload URL: %w" , err )
337- }
338-
339- rawURL , err := url .Parse ("https://raw.githubusercontent.com/" )
340- if err != nil {
341- return apiHost {}, fmt .Errorf ("failed to parse dotcom Raw URL: %w" , err )
342- }
343-
344- return apiHost {
345- baseRESTURL : baseRestURL ,
346- graphqlURL : gqlURL ,
347- uploadURL : uploadURL ,
348- rawURL : rawURL ,
349- }, nil
350- }
351-
352- func newGHECHost (hostname string ) (apiHost , error ) {
353- u , err := url .Parse (hostname )
354- if err != nil {
355- return apiHost {}, fmt .Errorf ("failed to parse GHEC URL: %w" , err )
356- }
357-
358- // Unsecured GHEC would be an error
359- if u .Scheme == "http" {
360- return apiHost {}, fmt .Errorf ("GHEC URL must be HTTPS" )
361- }
362-
363- restURL , err := url .Parse (fmt .Sprintf ("https://api.%s/" , u .Hostname ()))
364- if err != nil {
365- return apiHost {}, fmt .Errorf ("failed to parse GHEC REST URL: %w" , err )
366- }
367-
368- gqlURL , err := url .Parse (fmt .Sprintf ("https://api.%s/graphql" , u .Hostname ()))
369- if err != nil {
370- return apiHost {}, fmt .Errorf ("failed to parse GHEC GraphQL URL: %w" , err )
371- }
372-
373- uploadURL , err := url .Parse (fmt .Sprintf ("https://uploads.%s/" , u .Hostname ()))
374- if err != nil {
375- return apiHost {}, fmt .Errorf ("failed to parse GHEC Upload URL: %w" , err )
376- }
377-
378- rawURL , err := url .Parse (fmt .Sprintf ("https://raw.%s/" , u .Hostname ()))
379- if err != nil {
380- return apiHost {}, fmt .Errorf ("failed to parse GHEC Raw URL: %w" , err )
381- }
382-
383- return apiHost {
384- baseRESTURL : restURL ,
385- graphqlURL : gqlURL ,
386- uploadURL : uploadURL ,
387- rawURL : rawURL ,
388- }, nil
389- }
390-
391- func newGHESHost (hostname string ) (apiHost , error ) {
392- u , err := url .Parse (hostname )
393- if err != nil {
394- return apiHost {}, fmt .Errorf ("failed to parse GHES URL: %w" , err )
395- }
396-
397- restURL , err := url .Parse (fmt .Sprintf ("%s://%s/api/v3/" , u .Scheme , u .Hostname ()))
398- if err != nil {
399- return apiHost {}, fmt .Errorf ("failed to parse GHES REST URL: %w" , err )
400- }
401-
402- gqlURL , err := url .Parse (fmt .Sprintf ("%s://%s/api/graphql" , u .Scheme , u .Hostname ()))
403- if err != nil {
404- return apiHost {}, fmt .Errorf ("failed to parse GHES GraphQL URL: %w" , err )
405- }
406-
407- // Check if subdomain isolation is enabled
408- // See https://docs.github.com/en/enterprise-server@3.17/admin/configuring-settings/hardening-security-for-your-enterprise/enabling-subdomain-isolation#about-subdomain-isolation
409- hasSubdomainIsolation := checkSubdomainIsolation (u .Scheme , u .Hostname ())
410-
411- var uploadURL * url.URL
412- if hasSubdomainIsolation {
413- // With subdomain isolation: https://uploads.hostname/
414- uploadURL , err = url .Parse (fmt .Sprintf ("%s://uploads.%s/" , u .Scheme , u .Hostname ()))
415- } else {
416- // Without subdomain isolation: https://hostname/api/uploads/
417- uploadURL , err = url .Parse (fmt .Sprintf ("%s://%s/api/uploads/" , u .Scheme , u .Hostname ()))
418- }
419- if err != nil {
420- return apiHost {}, fmt .Errorf ("failed to parse GHES Upload URL: %w" , err )
421- }
422-
423- var rawURL * url.URL
424- if hasSubdomainIsolation {
425- // With subdomain isolation: https://raw.hostname/
426- rawURL , err = url .Parse (fmt .Sprintf ("%s://raw.%s/" , u .Scheme , u .Hostname ()))
427- } else {
428- // Without subdomain isolation: https://hostname/raw/
429- rawURL , err = url .Parse (fmt .Sprintf ("%s://%s/raw/" , u .Scheme , u .Hostname ()))
430- }
431- if err != nil {
432- return apiHost {}, fmt .Errorf ("failed to parse GHES Raw URL: %w" , err )
433- }
434-
435- return apiHost {
436- baseRESTURL : restURL ,
437- graphqlURL : gqlURL ,
438- uploadURL : uploadURL ,
439- rawURL : rawURL ,
440- }, nil
441- }
442-
443- // checkSubdomainIsolation detects if GitHub Enterprise Server has subdomain isolation enabled
444- // by attempting to ping the raw.<host>/_ping endpoint on the subdomain. The raw subdomain must always exist for subdomain isolation.
445- func checkSubdomainIsolation (scheme , hostname string ) bool {
446- subdomainURL := fmt .Sprintf ("%s://raw.%s/_ping" , scheme , hostname )
447-
448- client := & http.Client {
449- Timeout : 5 * time .Second ,
450- // Don't follow redirects - we just want to check if the endpoint exists
451- //nolint:revive // parameters are required by http.Client.CheckRedirect signature
452- CheckRedirect : func (req * http.Request , via []* http.Request ) error {
453- return http .ErrUseLastResponse
454- },
455- }
456-
457- resp , err := client .Get (subdomainURL )
458- if err != nil {
459- return false
460- }
461- defer resp .Body .Close ()
462-
463- return resp .StatusCode == http .StatusOK
464- }
465-
466- // Note that this does not handle ports yet, so development environments are out.
467- func parseAPIHost (s string ) (apiHost , error ) {
468- if s == "" {
469- return newDotcomHost ()
470- }
471-
472- u , err := url .Parse (s )
473- if err != nil {
474- return apiHost {}, fmt .Errorf ("could not parse host as URL: %s" , s )
475- }
476-
477- if u .Scheme == "" {
478- return apiHost {}, fmt .Errorf ("host must have a scheme (http or https): %s" , s )
479- }
480-
481- if strings .HasSuffix (u .Hostname (), "github.com" ) {
482- return newDotcomHost ()
483- }
484-
485- if strings .HasSuffix (u .Hostname (), "ghe.com" ) {
486- return newGHECHost (s )
487- }
488-
489- return newGHESHost (s )
490- }
491-
492- type userAgentTransport struct {
493- transport http.RoundTripper
494- agent string
495- }
496-
497- func (t * userAgentTransport ) RoundTrip (req * http .Request ) (* http .Response , error ) {
498- req = req .Clone (req .Context ())
499- req .Header .Set ("User-Agent" , t .agent )
500- return t .transport .RoundTrip (req )
501- }
502-
503- type bearerAuthTransport struct {
504- transport http.RoundTripper
505- token string
506- }
507-
508- func (t * bearerAuthTransport ) RoundTrip (req * http .Request ) (* http .Response , error ) {
509- req = req .Clone (req .Context ())
510- req .Header .Set ("Authorization" , "Bearer " + t .token )
511- return t .transport .RoundTrip (req )
512- }
513-
514- func addGitHubAPIErrorToContext (next mcp.MethodHandler ) mcp.MethodHandler {
515- return func (ctx context.Context , method string , req mcp.Request ) (result mcp.Result , err error ) {
516- // Ensure the context is cleared of any previous errors
517- // as context isn't propagated through middleware
518- ctx = errors .ContextWithGitHubErrors (ctx )
519- return next (ctx , method , req )
520- >> >> >> > main
521326 }
522327}
523328
0 commit comments