Victorqedu
Victorqedu

Reputation: 494

Java HttpURLConnection setRequestProperty is not setting custom header key

I want to send a custom http header request and I set the the custom keys like this:

con.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
con.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
con.setRequestProperty("Accept-Language", "ro-RO,ro;q=0.9,en-US;q=0.8,en;q=0.7");
con.setRequestProperty("Cache-Control", "max-age=0");
con.setRequestProperty("sec-ch-ua", "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"90\", \"Google Chrome\";v="90"");
con.setRequestProperty("sec-ch-ua-mobile", "?0");
con.setRequestProperty("Sec-Fetch-Dest", "document");
con.setRequestProperty("Sec-Fetch-Mode", "navigate");
con.setRequestProperty("Sec-Fetch-Site", "none");
con.setRequestProperty("Sec-Fetch-User", "?1");
con.setRequestProperty("Upgrade-Insecure-Requests", "1");
con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36");

The problem is that all properties that start with "sec" or "Sec" are not acctualy set.

I tested this with the method getRequestProperty right after setting them with setRequestProperty.

I also tested this by intercepting the https traffic with fiddler.

I also tried to set the request property using the method addRequestProperty instead setRequestProperty but the result was the same.

Why isn't Java accepting some of the properties?

UPDATE

Simple example:

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;

public class SetRequestProperty_example {
    public static void main(String[] args) {
        try {
            URL url = new URL("http://xyz.abc");
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestProperty("Sec-Fetch-Dest", "document");
            //con.addRequestProperty("Sec-Fetch-Dest", "document"); //same problem appears with addRequestProperty
            String check = con.getRequestProperty("Sec-Fetch-Dest");
            if(check==null) {
                System.err.println("Problem detected");
            } else {
                System.err.println("Problem solved");
            }
        } catch (IOException ex) {
            Logger.getLogger(SetRequestProperty_example.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

This simple code displays "Problem detected", what should I write to display "Problem solved"?

UPDATE This is weird but if I change the request property name from "Sec-Fetch-Dest" to "SSec-Fetch-Dest" then the property is set fine. This does not solve the problem but I think it could be a useful information.

Upvotes: 1

Views: 1491

Answers (1)

Alberto Chaves
Alberto Chaves

Reputation: 446

According to mozilla documentation, headers starting with "Sec" are part of the forbidden list, so they cannot be "in theory" modified programmatically.

A forbidden header name is the name of any HTTP header that cannot be modified programmatically; specifically, an HTTP request header name (in contrast with a Forbidden response header name).

Modifying such headers is forbidden because the user agent retains full control over them. Names starting with Sec- are reserved for creating new headers safe from APIs using Fetch that grant developers control over headers, such as XMLHttpRequest. Source: https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name

For this reason, when you try to invoke the "setRequestProperty" method, the header is not stored.

If you are on Java 11 or higher you can also try to use HttpClient, I tested the code and it's storing the header correctly on runtime, here is an example:

 HttpClient httpClient = HttpClient.newBuilder()
      .version(HttpClient.Version.HTTP_1_1)
      .connectTimeout(Duration.ofSeconds(10))
      .build();

 HttpRequest request = HttpRequest.newBuilder(
      URI.create("http://xyz.abc"))
      .header("Sec-Fetch-Dest", "document")
      .build();

 HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

// print status code
System.out.println(response.statusCode());

// print response body
System.out.println(response.body());

Upvotes: 3

Related Questions