Connecting External Service though Tyk Ingress gateway (oss)

We are trying to call an external service which is outside of K8s cluster through Tyk ingress which is created through tyk-operator. For this we have created a Service of type ExternalName.

apiVersion: v1
kind: Service
metadata:
  name: external-service
  namespace: tyk
spec:
  type: ExternalName
  externalName: httpbin.org
  ports:
  - port: 80

This service we have referred it in the Ingress -

apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
  name: httpbin-ingress-template
  labels:
    template: "true"
spec:
  name: tyk
  protocol: http
  active: true
  use_keyless: true
  proxy:
    target_url: http://httpbin.org
    listen_path: /v1/httpbin-ingress-api
    strip_listen_path: true
  version_data:
    default_version: Default
    not_versioned: true
    versions:
      Default:
        use_extended_paths: true
        name: Default
        global_headers:
          Host: "httpbin.org"
          uuid: "random"

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: httpbin-ingress
  annotations:
    kubernetes.io/ingress.class: tyk
    tyk.io/template: httpbin-ingress-template
spec:
  rules:
   - http: 
       paths:
         - path: /v1/httpbin-ingress-api
           pathType: Prefix
           backend:
             service:
               name: external-service
               port:
                 number: 80

When I call this API it is calling the ExternalName service properly but the call is failing because Host header is not set to “httpbin.org”.
I tried setting the Host header in global_headers in ApiDefinition but looks like it is not getting set. Other headers are getting set properly but the Host header.
Is there anything which I am missing here?

I just tried it and it works:

apiVersion: v1
kind: Service
metadata:
  name: external-httpbin
spec:
  type: ExternalName
  externalName: httpbin.org

---

apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
  name: external-httpbin
spec:
  name: external-httpbin
  protocol: http
  active: true
  use_keyless: true
  proxy:
    listen_path: /external-httpbin
    strip_listen_path: true
    target_url: http://external-httpbin.default.svc

And putting it in action

curl http://MYIP/external-httpbin/get                                    
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip", 
    "Host": "external-httpbin.default.svc", 
    "User-Agent": "curl/7.64.1", 
    "X-Amzn-Trace-Id": "Root=1-60795d11-021c6f4a24b54665356c43c6"
  }, 
  "origin": "MYIPS", 
  "url": "http://external-httpbin.default.svc/get"
}

I don’t think you need to set any of the custom middleware

    versions:
      Default:
        use_extended_paths: true
        name: Default
        global_headers:
          Host: "httpbin.org"
          uuid: "random"

Hi @ahmet ,
I tried with Ingress and it did not work, Is it working for you with Ingress also?

Yes - it’s working. Here is my ingress definition:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: httpbin-ingress
  annotations:
    kubernetes.io/ingress.class: tyk # <----------------- REFERENCES TYK INGRESS CONTROLLER
spec:
  rules:
    - host: myhttpbin
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: external-httpbin
                port:
                  number: 80

And here is the curl:

curl http://MYIP/get -H 'Host: myhttpbin'                                
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip", 
    "Host": "external-httpbin.default.svc.cluster.local", 
    "User-Agent": "curl/7.64.1", 
    "X-Amzn-Trace-Id": "Root=1-60796bfa-1edcb9716a77e5e63f5b2f5e"
  }, 
  "origin": "MYIP", 
  "url": "http://external-httpbin.default.svc.cluster.local/get"
}

Hi @ahmet ,

We have some proxy servers which validates the Host header and it rejects the request if it is not valid.
This external service calls are also getting rejected so we tried to add the Host header globally in API Definition but its not getting added.

Also I see Host header addition in gateway logs -

time="Apr 19 07:48:34" level=debug msg="Adding: Host" api_id=dHlrL2V4dGVybmFsLWh0dHBiaW4 api_name=external-httpbin mw=TransformHeaders org_id=oss origin=*.*.*.* path="/external-httpbin/get"

In the error message we see the External service Name URL instead of httpbin.org-

GET http://external-service.tyk.svc.cluster.local/get

I tried sending this host header in the request itself and added preserve_host_header: true parameter in API Definition and this time it worked.
Are there any issues only with Host header addition?

Hi I’m not sure that this is currently possible. I think it’s a middleware timing issue, where the header gets set, then overridden prior to proxying to the upstream.

Please open a feature request inside Tyk Gateway GitHub Repo. https://github.com/TykTechnologies/tyk/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=

Created below feature request for this -

2 Likes