http.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package proxy
  15. import (
  16. "context"
  17. "crypto/tls"
  18. "net/http"
  19. "net/http/httputil"
  20. "net/url"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/appctx"
  23. "yunion.io/x/onecloud/pkg/httperrors"
  24. )
  25. type EndpointGenerator func(context.Context, *http.Request) (string, error)
  26. type RequestManipulator func(ctx context.Context, r *http.Request) (*http.Request, error)
  27. type SEndpointFactory struct {
  28. generator EndpointGenerator
  29. serviceName string
  30. }
  31. func NewEndpointFactory(f EndpointGenerator, serviceName string) *SEndpointFactory {
  32. return &SEndpointFactory{
  33. generator: f,
  34. serviceName: serviceName,
  35. }
  36. }
  37. type SReverseProxy struct {
  38. *SEndpointFactory
  39. manipulator RequestManipulator
  40. }
  41. func NewHTTPReverseProxy(ef *SEndpointFactory, m RequestManipulator) *SReverseProxy {
  42. return &SReverseProxy{
  43. SEndpointFactory: ef,
  44. manipulator: m,
  45. }
  46. }
  47. func (p *SReverseProxy) ServeHTTP(ctx context.Context, w http.ResponseWriter, r *http.Request) {
  48. ctx = appctx.WithRequestLang(ctx, r)
  49. endpoint, err := p.generator(ctx, r)
  50. if err != nil {
  51. httperrors.InternalServerError(ctx, w, "%v", err)
  52. return
  53. }
  54. remoteUrl, err := url.Parse(endpoint)
  55. if err != nil {
  56. httperrors.InternalServerError(ctx, w, "failed parsing url %q: %v", endpoint, err)
  57. return
  58. }
  59. log.Debugf("Forwarding to servie: %q, url: %q", p.serviceName, remoteUrl.String())
  60. proxy := httputil.NewSingleHostReverseProxy(remoteUrl)
  61. proxy.Transport = &http.Transport{
  62. Proxy: http.ProxyFromEnvironment,
  63. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  64. DisableKeepAlives: true,
  65. }
  66. r, err = p.manipulator(ctx, r)
  67. if err != nil {
  68. httperrors.InternalServerError(ctx, w, "%v", err)
  69. return
  70. }
  71. proxy.ServeHTTP(w, r)
  72. }