Handling Cross-Origin Issues with Spring Cloud Gateway and HttpClient in Java

This article explains why browsers enforce same‑origin policies, presents common CORS solutions such as the @CrossOrigin annotation, HttpClient usage, and Spring Cloud Gateway integration, and provides detailed code examples for configuring gateways, CORS filters, and making HTTP requests in Java backend projects.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Handling Cross-Origin Issues with Spring Cloud Gateway and HttpClient in Java

Cross‑origin problems arise because browsers enforce the same‑origin policy, blocking interactions between different domains, ports, or protocols for security reasons.

Common ways to solve CORS include adding the @CrossOrigin annotation on controller classes, using a non‑browser HTTP client (e.g., Apache HttpClient), or routing requests through a gateway.

Annotation: @CrossOrigin

Adding @CrossOrigin to a controller enables cross‑domain access for the entire project.

Gateway Integration

Spring Cloud Gateway replaces Netflix Zuul, providing unified routing, security, monitoring, and rate‑limiting via a filter chain.

Routing : Each route has an ID, URI, predicates, and filters. When predicates match, the request is forwarded to the target service.

Predicates : Functions based on ServerWebExchange allow matching request headers, parameters, etc.

Filters : Two types – Gateway Filter and Global Filter – modify requests and responses.

<dependencies>
    <!-- Public module dependencies -->
    <dependency>
        <groupId>com.lzq</groupId>
        <artifactId>service_utils</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

Configuration file (application.yml):

# Service port
server.port=9090
# Service name
spring.application.name=service-gateway
# Nacos address
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8888
# Enable discovery‑based routing
spring.cloud.gateway.discovery.locator.enabled=true
# Route definitions
spring.cloud.gateway.routes[0].id=service-hosp
spring.cloud.gateway.routes[0].uri=lb://service-hosp
spring.cloud.gateway.routes[0].predicates=Path=/*/hosp/**
... (other routes)

Startup class:

@SpringBootApplication
public class ApiGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiGatewayApplication.class, args);
    }
}

Update the front‑end .evn file to point to the gateway port.

CORS Configuration Class

@Configuration
public class CorsConfig {
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedMethod("*");
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
}

If you previously used @CrossOrigin, remove it after adding the global filter.

HttpClient Usage

Typical scenarios include inter‑system API calls and web crawling.

Native Java URL connection example (fetching Baidu homepage):

public class HttpTest {
    @Test
    public void test1() throws Exception {
        String url = "https://www.badu.com";
        URL url1 = new URL(url);
        URLConnection urlConnection = url1.openConnection();
        HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
        InputStream is = httpURLConnection.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        httpURLConnection.setRequestMethod("GET");
        httpURLConnection.setRequestProperty("Accept-Charset", "utf-8");
    }
}

Using Apache HttpClient:

Create an HttpClient instance.

Instantiate HttpGet or HttpPost with the target URL.

Set parameters via setParams or setEntity for POST.

Execute the request with client.execute(request) to obtain an HttpResponse.

Read response headers and body via getAllHeaders(), getHeaders(), and getEntity().

Always release the connection.

Dependency for HttpClient:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

Integration test example:

@Test
public void test2() {
    CloseableHttpClient client = HttpClients.createDefault();
    String url = "https://www.baidu.com";
    HttpGet httpGet = new HttpGet(url);
    CloseableHttpResponse response = null;
    try {
        response = client.execute(httpGet);
        String result = EntityUtils.toString(response.getEntity(), "utf-8");
        System.out.println(result);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (client != null) {
            try { client.close(); } catch (IOException e) { e.printStackTrace(); }
        }
    }
}

Service Example: Saving Hospital Data

@RequestMapping(value="/hospital/save", method=RequestMethod.POST)
public String saveHospital(String data, HttpServletRequest request) {
    try {
        apiService.saveHospital(data);
    } catch (YyghException e) {
        return this.failurePage(e.getMessage(), request);
    } catch (Exception e) {
        return this.failurePage("数据异常", request);
    }
    return this.successPage(null, request);
}
@Override
public boolean saveHospital(String data) {
    JSONObject jsonObject = JSONObject.parseObject(data);
    Map<String, Object> paramMap = new HashMap<>();
    paramMap.put("hoscode", "10000");
    paramMap.put("hosname", jsonObject.getString("hosname"));
    paramMap.put("logoData", jsonObject.getString("logoData"));
    JSONObject response = HttpRequestHelper.sendRequest(paramMap, this.getApiUrl() + "/api/hosp/saveHospital");
    if (response != null && response.getIntValue("code") == 200) {
        return true;
    } else {
        throw new YyghException(response.getString("message"), 201);
    }
}
public static JSONObject sendRequest(Map<String, Object> paramMap, String url) {
    String result = "";
    try {
        StringBuilder postdata = new StringBuilder();
        for (Map.Entry<String, Object> param : paramMap.entrySet()) {
            postdata.append(param.getKey()).append("=").append(param.getValue()).append("&");
        }
        byte[] reqData = postdata.toString().getBytes("utf-8");
        byte[] respdata = HttpUtil.doPost(url, reqData);
        result = new String(respdata);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return JSONObject.parseObject(result);
}
public static byte[] send(String strUrl, String reqmethod, byte[] reqData) {
    try {
        URL url = new URL(strUrl);
        HttpURLConnection httpcon = (HttpURLConnection) url.openConnection();
        httpcon.setDoOutput(true);
        httpcon.setDoInput(true);
        httpcon.setUseCaches(false);
        httpcon.setInstanceFollowRedirects(true);
        httpcon.setConnectTimeout(CONN_TIMEOUT);
        httpcon.setReadTimeout(READ_TIMEOUT);
        httpcon.setRequestMethod(reqmethod);
        httpcon.connect();
        if (reqmethod.equalsIgnoreCase(POST)) {
            OutputStream os = httpcon.getOutputStream();
            os.write(reqData);
            os.flush();
            os.close();
        }
        BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream(), "utf-8"));
        String inputLine;
        StringBuilder buffer = new StringBuilder();
        while ((inputLine = in.readLine()) != null) {
            buffer.append(inputLine);
        }
        in.close();
        httpcon.disconnect();
        return buffer.toString().getBytes();
    } catch (Exception ex) {
        log.error(ex.toString(), ex);
        return null;
    }
}

API controller exposing the hospital save endpoint:

@RestController
@RequestMapping("/api/hosp")
public class ApiController {
    @Autowired
    private HospitalService hospitalService;
    @PostMapping("saveHospital")
    public R saveHospital(HttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, Object> paramMap = HttpRequestHelper.switchMap(parameterMap);
        String mapStr = JSONObject.toJSONString(paramMap);
        Hospital hospital = JSONObject.parseObject(mapStr, Hospital.class);
        hospitalService.saveHosp(hospital);
        return R.ok();
    }
}

With these configurations and code examples, developers can effectively resolve CORS issues, route requests through Spring Cloud Gateway, and perform HTTP calls using both native Java and Apache HttpClient in backend Java applications.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

MicroservicesCORSCross-OriginSpring Cloud GatewayHttpClient
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.