4

I'm trying to introduce a Spring Boot REST service in our development setup. The development setup is using docker-compose and an API gateway to expose the individual services on the same domain (ie. localhost).

When I try to make a HTTP request to my service from inside another container via the service name in the shared docker-compose file, the service returns a 400.

The setup

I've edited our docker-compose file, so it looks like the below to introduce the Spring Boot Java service. The service is based on spring-boot-starter-parent (2.0.3.RELEASE) and spring-boot-starter-web. I haven't configured anything related to the web server (except adding the server.server-header property to ensure myself that the request is hitting my service).

version: '3'
services:
  ...

  hello_java:
    build:
      context: ../hello-java/
      dockerfile: Dockerfile
    depends_on:
      - postgres
      - castle_black
    ports:
      - "8301:8080"

  castle_black:
    build: ../castle-black/tyk-gateway
    ports:
      - "8191:8080"
    depends_on:
      - redis

The behaviour

If I request the hello service from outside the containers (e.g. in my browser on localhost:8301) it replies back correctly. If I'm inside a container, but obtain the IP that the container with my new service gets in the docker network and use that the new service also responds correctly back.

Below I have shown a request from inside the API gateway container to the Java service, first by using the service name and then afterwards with the IP that was resolved. It only replies with a correct response in the IP case.

# curl -v http://hello_java:8080/hello-java/greet?username=Java
* Hostname was NOT found in DNS cache
*   Trying 172.19.0.6...
* Connected to hello_java (172.19.0.6) port 8080 (#0)
> GET /hello-java/greet?username=Java HTTP/1.1
> User-Agent: curl/7.35.0
> Host: hello_java:8080
> Accept: */*
> 
< HTTP/1.1 400 
< Transfer-Encoding: chunked
< Date: Wed, 01 Aug 2018 11:34:34 GMT
< Connection: close
* Server MySpringBootApp is not blacklisted
< Server: MySpringBootApp
< 
* Closing connection 0

# curl -v http://172.19.0.6:8080/hello-java/greet?username=Java
* Hostname was NOT found in DNS cache
*   Trying 172.19.0.6...
* Connected to 172.19.0.6 (172.19.0.6) port 8080 (#0)
> GET /hello-java/greet?username=Java HTTP/1.1
> User-Agent: curl/7.35.0
> Host: 172.19.0.6:8080
> Accept: */*
> 
< HTTP/1.1 200 
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 10
< Date: Wed, 01 Aug 2018 11:34:55 GMT
* Server MySpringBootApp is not blacklisted
< Server: MySpringBootApp
< 
* Connection #0 to host 172.19.0.6 left intact
Hello Java

The questions

Is there something in the standard spring-boot-starter-web setup that prevents the web server from servicing the request, when the client adds the "Host: hello_java:8080" header? Or why is the web server behaving differently in the two scenarios? And what can I do about it?

Morten Olsen
  • 161
  • 1
  • 6
  • You mentioned an API gateway (Zuul, Spring Cloud Gateway, ...?) - is your gateway a service itself (and part of the docker container)? If not, the gateway (outside) and the services (inside the container) have a different "localhost" and the gateway can't set up proxies. – Bennett Dams Aug 01 '18 at 12:08
  • The API gateway is tyk.io and it is running in the second container in the compose file. When I just run bash in the API gateway container, I can access the web server in the hello_java container. If I make an HTTP request to hello_java the web-server is responding back with a 400 status code, while if I make the request to the IP that hello_java resolves to in the container it gives a correct response (200 OK). – Morten Olsen Aug 01 '18 at 12:34

2 Answers2

12

After some experimentation it turned out that the it was the underscore in the service name that caused the issue. Changing the service name to not have an underscore solved the problem.

Morten Olsen
  • 161
  • 1
  • 6
  • 1
    this. the solution presented here helped me as well after countless hours of debugging. while i still have services containing ONE underscore in their name and my nginx reverse proxy having no issues routing requests to them, it would refuse to do so when i introduced a service containing TWO underscores. I now completely renamed the service in question (to just be a single word) and things started working. so thanks OP for sharing this with us! – salgmachine Dec 23 '20 at 10:33
  • 3
    I have never been so angry at finding a solution. Thank you very much for posting this, I never would have guessed this was the problem – jamzsabb Mar 03 '21 at 20:23
2

RFC 952 stipulates that "name" (Net, Host, Gateway, or Domain name) is a text string up to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus sign (-), and period (.)

It seems that the _ is not a valid component for host names. It's a bit confusing because I had the same problem and when I ping app_server it's fine but when I wget from app_server I got bad request.

Changing the underscore to minus fixed it for me.

  • I am sorry but your assertion is not correct. RFC952 has been updated by other RFCs (e.g. to allow for a digit as first symbol), not obsoleted. I don't have the time to go through all RFCs from the transitive closure of the 'updated by' relation but I would assume that the restrictions on the use of underscore for hostnames still stands. If it doesn't, please point to the appropriate RFC where the restriction is relaxed. In any case, dropping the underscore from the names fixed the problem for me. – Nikolay Mihaylov Nov 01 '18 at 15:13