Understanding Cross-Origin Issues and Solutions with Spring Cloud Gateway and HttpClient

This article explains why browsers enforce same‑origin policies causing CORS problems, outlines common remedies such as the @CrossOrigin annotation, HttpClient usage, and Spring Cloud Gateway integration, and provides detailed configuration and code examples for implementing these solutions in a Java backend.

Architect's Guide
Architect's Guide
Architect's Guide
Understanding Cross-Origin Issues and Solutions with Spring Cloud Gateway and HttpClient

Because browsers enforce the same‑origin policy, requests from different ports, protocols, or domains trigger cross‑origin (CORS) restrictions, preventing interaction for security reasons.

Common ways to resolve CORS include adding the @CrossOrigin annotation in controller layers, using HttpClient (which does not rely on a browser), or routing requests through an API gateway.

Spring Cloud Gateway Integration

Spring Cloud Gateway replaces Netflix Zuul, offering unified routing and filter capabilities such as security, monitoring, and rate limiting. Its core concepts are:

Routing : defines an ID, target URL, predicates, and filters; a request matches a route when its predicates evaluate to true.

Predicates : functions (e.g., ServerWebExchange) that inspect request attributes like headers or parameters.

Filters : either GatewayFilter or GlobalFilter, which can modify requests and responses.

The gateway receives a request, matches it via GatewayHandlerMapping, forwards it to the appropriate service through the filter chain, and returns the response.

Project Setup

Create a new module service_gateway and add the following Maven dependencies:

<dependencies>
    <!-- Common utilities -->
    <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 (application.yml or properties):

# 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/**
spring.cloud.gateway.routes[1].id=service-cmn
spring.cloud.gateway.routes[1].uri=lb://service-cmn
spring.cloud.gateway.routes[1].predicates=Path=/*/cmn/**
spring.cloud.gateway.routes[2].id=service-user
spring.cloud.gateway.routes[2].uri=lb://service-user
spring.cloud.gateway.routes[2].predicates=Path=/*/userlogin/**

Startup class:

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

Adjust the front‑end .env file to point to the gateway port, and the gateway will handle CORS by allowing the request to pass through to downstream services.

HttpClient Usage

Typical scenarios for HttpClient include inter‑system API calls and web crawling. A simple example of fetching a page with Java's native HttpURLConnection:

public class HttpTest {
    @Test
    public void test1() throws Exception {
        String url = "https://www.baidu.com";
        URL url1 = new URL(url);
        URLConnection urlConnection = url1.openConnection();
        HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
        httpURLConnection.setRequestMethod("GET");
        httpURLConnection.setRequestProperty("Accept-Charset", "utf-8");
        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);
        }
    }
}

Using Apache HttpClient:

Create an HttpClient instance.

Instantiate HttpGet or HttpPost with the target URL.

Set parameters via setParams (for both GET and POST) or setEntity (for POST).

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

Extract headers with getAllHeaders() or getHeaders(String name), and retrieve the response body via getEntity().

Always release the connection after use.

Dependency for Maven:

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

Example test method:

@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(); }
        }
    }
}

Helper Utilities

HttpRequestHelper

encapsulates synchronous POST requests:

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);
}
HttpUtil

performs low‑level HTTP operations:

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.setConnectTimeout(CONN_TIMEOUT);
        httpcon.setReadTimeout(READ_TIMEOUT);
        httpcon.setRequestMethod(reqmethod);
        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"));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = in.readLine()) != null) {
            sb.append(line);
        }
        in.close();
        httpcon.disconnect();
        return sb.toString().getBytes();
    } catch (Exception ex) {
        log.error(ex.toString(), ex);
        return null;
    }
}

These utilities enable different systems to call each other’s APIs, such as a hospital service saving data via a POST request to /api/hosp/saveHospital.

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.

Javaapi-gatewayCORSSpring Cloud GatewayHttpClient
Architect's Guide
Written by

Architect's Guide

Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.

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.