- Run the Spring Boot application (it will run on http://localhost:8088 by default).
- Run the frontend HTML on a different web server (e.g., using the Live Server extension in VS Code, typically running on http://localhost:5500).
- Open a browser and access the HTML page.
- Click the "Fetch Data" button and observe the results.
When you click the button, the frontend will send a request to /api/redirect. Spring Boot will return a 302 redirect to /api/data. The browser will automatically follow this redirect and receive data from /api/data.
- CORS has been properly configured on the backend to allow requests from the frontend domain.
- The browser automatically handles the redirect, so you will receive the final data without needing to explicitly handle the redirect in the frontend code.
- If you want to control the redirect process, you can use
redirect: 'manual'in thefetch()options. - To check for CORS errors when not properly configured, you can comment out the
@CrossOriginannotations in the backend code for eachredirect()andgetData()method, or comment out both methods. Then, open the Console and Network tabs in the browser to observe the errors.
- CORS (Cross-Origin Resource Sharing) only applies to HTTP requests made by JavaScript from the browser (e.g., using XMLHttpRequest or Fetch API).
- CORS does not apply to regular browser redirects, page loads, or form submissions.
- When you make an AJAX request (using
XMLHttpRequestorFetch API) and the server returns a 302 Redirect status code, the browser will automatically follow the redirect to the new URL specified in theLocationheader. You don't need to handle the redirect explicitly in your frontend code, unless you want to control this process. - Although the browser follows the redirect, if the target domain doesn't provide the necessary CORS headers, access to the final response content may be blocked. This happens for security reasons, preventing access to data from unauthorized sources.
-
With Fetch API:
-
By default,
fetch()will automatically follow redirects (the default value for theredirectoption is'follow'). -
You can change this behavior by setting
redirectto'manual'or'error'. -
Example:
fetch('https://backend.example.com/api/data', { redirect: 'follow' }) .then(response => { // The browser has followed the redirect, you receive the final response });
-
-
With XMLHttpRequest:
- Similarly,
XMLHttpRequestalso automatically follows redirects. - You can't change this behavior in
XMLHttpRequest; it will always automatically follow redirects.
- Similarly,
If you need to know whether a redirect has occurred or want to control sending credentials during the redirect process, you can set redirect to 'manual' in fetch().
fetch('https://backend.example.com/api/data', { redirect: 'manual' })
.then(response => {
if (response.type === 'opaqueredirect') {
// A redirect has occurred, but you can't access the redirect URL due to CORS policy
// You can decide on the next action based on this situation
} else {
// Handle normal response
}
});fetch('https://backend.example.com/api/data', { redirect: 'manual' })
.then(response => {
if (response.status === 302) {
const redirectUrl = response.headers.get('Location');
// Perform action with the redirect URL
// Example: Send a new request to the redirect URL
return fetch(redirectUrl, { credentials: 'include' });
} else {
return response;
}
})
.then(response => response.json())
.then(data => {
// Process the received data
console.log(data);
})
.catch(error => {
console.error('Error:', error);
});@GetMapping("/api/redirect")
public RedirectView redirect() {
return new RedirectView("/api/data");
}
@GetMapping("/api/data")
public String getData() {
return "This is the redirected data!";
}- With Direct URL Access (typing http://localhost:8088/api/redirect in the address bar) ⇒ Always successful
📔 Reminder: CORS does not apply to regular browser redirects, page loads, or form submissions.
- With AJAX/Fetch ⇒ CORS Error
| Console Tab: | Network Tab: |
|---|---|
![]() |
![]() |
@GetMapping("/api/redirect")
public RedirectView redirect() {
return new RedirectView("/api/data");
}
@GetMapping("/api/data")
@CrossOrigin(origins = {"http://localhost:5500", "http://127.0.0.1:5500"}, allowCredentials = "true")
public String getData() {
return "This is the redirected data!";
} - With AJAX/Fetch ⇒ CORS Error same as Case 1
📔 Reminder: If the target domain doesn't provide the necessary CORS headers, access to the final response content may be blocked.
Here, the first target domain is /redirect, so it fails immediately.
@GetMapping("/api/redirect")
@CrossOrigin(origins = {"http://localhost:5500", "http://127.0.0.1:5500"}, allowCredentials = "true")
public RedirectView redirect() {
return new RedirectView("/api/data");
}
@GetMapping("/api/data")
public String getData() {
return "This is the redirected data!";
} - With AJAX/Fetch ⇒ CORS Error when calling
/data
| Console Tab: | Network Tab: |
|---|---|
![]() |
![]() |
📔 Reminder: If the target domain doesn't provide the necessary CORS headers, access to the final response content may be blocked.
Here, the target domain is /data, so it fails.
@GetMapping("/api/redirect")
@CrossOrigin(origins = {"http://localhost:5500", "http://127.0.0.1:5500"}, allowCredentials = "true")
public RedirectView redirect() {
return new RedirectView("/api/data");
}
@GetMapping("/api/data")
@CrossOrigin(origins = {"http://localhost:5500", "http://127.0.0.1:5500"}, allowCredentials = "true")
public String getData() {
return "This is the redirected data!";
} - With Direct URL Access (typing http://localhost:8088/api/redirect in the address bar) ⇒ Still always successful
- With AJAX/Fetch ⇒ Successful
| Console Tab: | Network Tab: |
|---|---|
![]() |
![]() |






