skip to Main Content

I have two applications where spring is the backend and react is the frontend. I setup everything, including the response, so whenever I test using Postman, I always get the header below

postman
and in the frontend, I setup like this:

Api.js

// api.js
import axios from 'axios';
import uri from "../routes/uri";

const instance = axios.create({
    baseURL: uri.baseUrl, // Replace with your API base URL
    headers: {
        'Content-Type': 'application/json',
        'Authorization':''
        // 'Authorization': 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJsaW5kYSIsImF1dGhvcml0aWVzIjpbeyJhdXRob3JpdHkiOiJzdHVkZW50OndyaXRlIn0seyJhdXRob3JpdHkiOiJzdHVkZW50OnJlYWQifSx7ImF1dGhvcml0eSI6ImNvdXJzZTpyZWFkIn0seyJhdXRob3JpdHkiOiJST0xFX0FETUlOIn0seyJhdXRob3JpdHkiOiJjb3Vyc2U6d3JpdGUifV0sImlhdCI6MTY4OTM1MTg0NSwiZXhwIjoxNjkwMjE0NDAwfQ.Cw8-e6U_aQ-3SyDjmGKq5cDDcp-omv3fgEzoS2Aiwu69hrn8Wh3VmQgXstOQYUNfK4lt7npOIB-r26F8CCum6Q'
        // You can add any other common headers here, such as authentication tokens, etc.
    },
});

// instance.interceptors.request.use((config) => {
//     // Add your custom headers here
//     config.headers['Authorization'] = 'saasda';
//     return config;
// });

instance.interceptors.response.use(
    (response) => {
        console.log('Response Data:', response.headers);
        const customHeaderValue = response.headers['Authorization']; // Replace with your custom header key
        if (customHeaderValue) {
            instance.defaults.headers['Authorization'] = customHeaderValue; // Replace with your custom header key for requests
        }
        return response;
    },
    (error) => {
        return Promise.reject(error);
    }
);

export default instance;

ApiService.js

// apiService.js
import api from './api';

const apiService = {
    async get(endpoint) {
        try {
            const response = await api.get(endpoint);
            return response.data;
        } catch (error) {
            console.log(error);
            throw new Error('An error occurred while fetching data.');

        }
    },

    async post(endpoint, data) {
        try {
            const response = await api.post(endpoint, data);
            return response.data;
        } catch (error) {
            console.log(error);
            throw new Error('An error occurred while posting data.');


        }
    },

    // Add other methods like PUT, DELETE, etc., as needed.
};

export default apiService;

And calling API

    const handleGetRequest = async () => {
        try {
            const responseData = await apiService.post(uri.getEmployee);

            const contentArray = Object.values(responseData.data.content); // convert into array since react can only disapl
            setData(contentArray);

        } catch (error) {
            console.error(error);
            // console.log(error.message());

        }
    };

I also tried setup the CORS config

const express = require('express');
const cors = require('cors');
const app = express();

// Allow specific origins (e.g., 'http://localhost:3000' for your React app)
const allowedOrigins = ['http://localhost:3000'];

// CORS middleware configuration
app.use(
    cors({
        origin: (origin, callback) => {
            if (allowedOrigins.includes(origin) || !origin) {
                callback(null, true);
            } else {
                callback(new Error('Not allowed by CORS'));
            }
        },
    })
);

// Your API routes and other configurations
// ...

const port = 8080;
app.listen(port, () => {
    console.log(`Server started on port ${port}`);
});

However, in the browser, I only get a response Browser response. Why Authorization does not appear in the browser response? and what should I do properly get the custom header from BE as response.

I tried to add header in response but the value must be coming from api/backend.

instance.interceptors.response.use(
    (response) => {
        response.headers['Authorization'] = '';
        // console.log('Response Data:', response.headers);
        const customHeaderValue = response.headers['Authorization']; // Replace with your custom header key
        if (customHeaderValue) {
            instance.defaults.headers['Authorization'] = customHeaderValue; // Replace with your custom header key for requests
        }
        return response;
    },
    (error) => {
        return Promise.reject(error);
    }
);

And this only result om empty header value. empty header value

2

Answers


  1. Chosen as BEST ANSWER

    After days of trial, I found the error. Apparently, the issue seems to be using apiService as the wrapper. Whenever the request is made, the application does not have the same response header as the request. There's no need to set up extra proxy config and credentials.

    So here is my new wrapper.

    apiWrapper.js

    const apiWrapper = async (url, method, data, customHeaders = {}) => {
        try {
            const response = await api({
                url,
                method,
                data,
                headers: {
                    'Content-Type': 'application/json',
                    'X-Custom-Header': 'Custom Value',
                    'Authorization': '',
                    // Default Content-Type
                    ...customHeaders, // Include custom headers passed to the wrapper
                },
            });
    
            return response.data;
        } catch (error) {
            throw error;
        }
    };
    

    api.js

    // api.js
    import axios from 'axios';
    import uri from "../routes/uri";
    
    const instance = axios.create({
        baseURL: uri.baseUrl,
    });
    
    instance.interceptors.request.use(
        config => {
            const token = localStorage.getItem('Authorization');
            // Replace with your way of getting the access token (e.g., from localStorage)
    
            if (token) {
                config.headers['Authorization'] = token;
            }
    
            return config;
        },
        error => {
            return Promise.reject(error);
        }
    );
    
    instance.interceptors.response.use(
        (response) => {
            const customHeaderValue = response.headers['authorization']; // Replace with your custom header key
            if (customHeaderValue) {
                instance.defaults.headers['Authorization'] = customHeaderValue; // Replace with your custom header key for requests
                localStorage.setItem('Authorization', customHeaderValue);
                localStorage.setItem('Authorization', customHeaderValue);
            } else {
                localStorage.setItem('is_authenticated', "false");
                localStorage.set( 'test', false );
            }
            return response;
        },
        (error) => {
            return Promise.reject(error);
        }
    );
    
    export default instance;
    

    and to use it,

     const responseData = await apiWrapper(uri.login, 'POST', formData);
    

  2. You can use withCredentials property.

    axios.get(BASE_URL + '/todos', { withCredentials: true, credentials: 'include' });
    

    Also its possible to force credentials to every Axios requests

    axios.defaults.withCredentials = true
    

    Or using credentials for some of the Axios requests as the following code

    const instance = axios.create({
       withCredentials: true,
       credentials: 'include',
       baseURL: BASE_URL
    })
    

    By setting { withCredentials: true } you may encounter cross origin issue. To solve that you need to use

    app.use(
        cors({
            allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization'],
            credentials: true,
            origin: (origin, callback) => {
                if (allowedOrigins.includes(origin) || !origin) {
                    callback(null, true);
                } else {
                    callback(new Error('Not allowed by CORS'));
                }
            },
        })
    );
    

    You can also play around the headers response and Access-Control-Allow-Headers to indicate which HTTP headers can be used during the actual request.

    allowedHeaders: Configures the Access-Control-Allow-Headers CORS
    header. Expects a comma-delimited string (ex:
    ‘Content-Type,Authorization’) or an array (ex: [‘Content-Type’,
    ‘Authorization’]). If not specified, defaults to reflecting the
    headers specified in the request’s Access-Control-Request-Headers
    header.

    Note that the Authorization header always needs to be listed explicitly

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search