Skip to content

Adds the possibility to change the USE_TLS_RESPONSE HTTP response#709

Open
Leon-Schwandt wants to merge 2 commits intoapache:mainfrom
Leon-Schwandt:main
Open

Adds the possibility to change the USE_TLS_RESPONSE HTTP response#709
Leon-Schwandt wants to merge 2 commits intoapache:mainfrom
Leon-Schwandt:main

Conversation

@Leon-Schwandt
Copy link
Copy Markdown

Enables the USE_TLS_RESPONSE message to be changed at a global level. A possible use case would be a redirect to HTTPS

@tobiasbaum
Copy link
Copy Markdown

I would like to see this feature added to Tomcat. Does anyone know the reason why it has not been merged, yet?

Some background on my use case:

When I have a secure (https) connector listening on some port (say 8080) and I accidentally call it without TLS (e.g., http://localhost:8080/ instead of https://localhost:8080/), I get an error response as follows:
Bad Request
This combination of host and port requires TLS.

For non-technical users, this error response is not ideal. Therefore, I would like to be able to configure this response. Ideally in my case, the response would be a redirect that changes the protocol from http to https and leaves the remaining url the same. But serving a custom static HTML response would be sufficient, too (as I could then, e.g., implement the redirect in JavaScript or provide a user-friendly explanation). Also, in my case, configuration via code would be sufficient as I run Tomcat embedded as a library.

@Leon-Schwandt
Copy link
Copy Markdown
Author

This is my first pull request in a public repository, so I don’t have much experience with this yet. Since I didn’t receive any response to my pull request for months, I didn’t follow up on it. That’s why I didn’t notice the merge conflict. I’d also be interested to know why my PR hasn’t been merged yet; exactly what @tobiasbaum described was also my thought, which is why I created the PR two years ago.

Enables the USE_TLS_RESPONSE message to be changed at a global level. A possible use case would be a redirect to HTTPS
@Leon-Schwandt
Copy link
Copy Markdown
Author

I've rebased the PR onto the current main branch and resolved all merge conflicts (including removing changes to SecureNio2Channel.java since NIO2 was dropped in Tomcat 12).

@rmaucher
Copy link
Copy Markdown
Contributor

This seems to have no practical use as is. There needs to be another mechanism to implement this otherwise it's clearly not an option.

@tobiasbaum
Copy link
Copy Markdown

@rmaucher Can you elaborate a bit on what you mean with "no practical use as is"? Do you see a problem with the use case I described or with the specific solution Leon-Schwandt implemented (and which)?

@rmaucher
Copy link
Copy Markdown
Contributor

Add a configuration for the string, it would be more than enough.

@Leon-Schwandt
Copy link
Copy Markdown
Author

Do you mean something like that?

@SpringBootApplication
@RestController
public class MyApplication {

    @Value("classpath:static/index.html")
    private Resource htmlFile;

    static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @GetMapping("/")
    public String helloWorld() {
        return "Hello World!";
    }

    @EventListener
    public void onServerInitialized(WebServerInitializedEvent event) throws IOException {
        final String html = htmlFile.getContentAsString(UTF_8);
        // @formatter:off
        final String httpResponse = "HTTP/1.1 200 \r\n" +
                "Content-Type: text/html;charset=UTF-8\r\n" +
                "Connection: close\r\n" +
                "\r\n" +
                html;
        // @formatter:on
        TLSClientHelloExtractor.USE_TLS_RESPONSE = httpResponse.getBytes(UTF_8);
    }

}
image

This is just a (intentionally brief) example, but it wouldn't require any changes to Tomcat's source code. If this is what you meant, perhaps this option could be documented somewhere or posted as a note so that other users are informed about it.

@Leon-Schwandt
Copy link
Copy Markdown
Author

The only thing I haven't found an elegant solution for yet is distinguishing between a small redirect page for users and a technical response for an API call.

@tobiasbaum
Copy link
Copy Markdown

This works for me. Somehow, I didn't notice that TLSClientHelloExtractor.USE_TLS_RESPONSE is non-final and part of the public API. Sorry for that and thanks for putting me on the right path!

@Leon-Schwandt For your API use case: Would it be a solution to not use HTTP status code 200 but some other code so that the API client can easily distinguish a valid response from this one? For a user, the status code should be mostly irrelevant.

@Leon-Schwandt
Copy link
Copy Markdown
Author

I'm glad my example was helpful to you. But what if I want to manage a website, for example, at https://example.com/index.html, and an API, for example, at https://example.com/api/user, using just one server? With a single public field, I can't distinguish between the two different requests. The browser also accepts an HTTP 302 response with a webpage, meaning it displays the content. However, I cannot return a webpage to the user and provide technical information to the API call, for example in the form of JSON.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants