Is there a means to set the host & port for the Spring HATEOAS `ControllerLinkBuilder`?

前端 未结 2 1568
故里飘歌
故里飘歌 2021-01-12 06:13

Spring HATEOAS provides the handy ControllerLinkBuilder to create links to controller methods, which will be added as hrefs in the JSON/XML returned to a client

2条回答
  •  清歌不尽
    2021-01-12 07:02

    A pure answer to the question I originally posed seems to involve writing my own ControllerLinkBuilder implementation which has the option of building the URL based on environment variables that I set. I may do that.

    However, the reason I was trying to force the URL is that there is a bug in the ControllerLinkBuilder. It's worth noting that this bug is a bug in code which was copied from ServletUriComponentsBuilder.

    String scheme = request.getScheme();
    
    // The port number retrieved here is the port set by server.port
    int port = request.getServerPort();
    String host = request.getServerName();
    
    String header = request.getHeader("X-Forwarded-Host");
    
    if (StringUtils.hasText(header)) {
        String[] hosts = StringUtils.commaDelimitedListToStringArray(header);
        String hostToUse = hosts[0];
        if (hostToUse.contains(":")) {
            String[] hostAndPort = StringUtils.split(hostToUse, ":");
            host  = hostAndPort[0];
    
            // Note that the port is set if there is a ":" in the address.
            port = Integer.parseInt(hostAndPort[1]);
        }
        else {
            host = hostToUse;
        }
    }
    
    ServletUriComponentsBuilder builder = new ServletUriComponentsBuilder();
    builder.scheme(scheme);
    builder.host(host);
    
    // Here lies the bug...
    if ((scheme.equals("http") && port != 80) || (scheme.equals("https") && port != 443)) {
        builder.port(port);
    }
    

    Basically, the port is only set when the server.port is not 80 or 443, rather than being based on the port used for the request. This means that if the X-Forwarded-Host is using a default port for the scheme (and therefore not having anything after the ":"), then the application port will be used instead of the default.

提交回复
热议问题