Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backend only works in localhost React + Springboot + docker

I'm trying to deploy a React + Spring Boot App.

3 docker containers with compose (client+server+database) and everything works on localhost. I can access the frontend, login/register, and use the web service as expected.

client: localhost:3333
server: localhost:8080

Once i try deploy it on another machine (desktop w/ ubuntu server), im able to acess the frontend / backend and send requests via postman (ex: POST a new user to 192.168.1.x:8080/api/account/register.)

192.168.1.x:3333
192.168.1.x:8080

Problem:

If i try to acess 192.168.1.x:3333 or 192.168.1.x:8080 in another machine (same network) or my-ip:333 (another network) it works, but pressing Login/Register wont work. (this only works on the host machine)

Devtools Firefox:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/api/account/login. (Reason: CORS request did not succeed). Status code: (null).

Devtools Chrome:

Failed to load resource: net::ERR_CONNECTION_REFUSED localhost:8080/api/account/login:1          
TypeError: Failed to fetch

EDIT (23/05/2022)

I still couldn´t solve the issue

WebSecurity.java

@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
    private UserDetailsService userDetailsService;
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private DataSource dataSource;

    public WebSecurity(UserDetailsService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.userDetailsService = userDetailsService;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // Comment to disable authentication
        http.cors().and().csrf().disable().authorizeRequests().antMatchers(HttpMethod.POST, ACESSABLE).permitAll()
                .anyRequest().authenticated().and().addFilter(new JWTAuthenticationFilter(authenticationManager()))
                .addFilter(new JWTAuthorizationFilter(authenticationManager()))
                // this disables session creation on Spring Security
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        // auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
        auth.jdbcAuthentication().dataSource(dataSource)
                .usersByUsernameQuery("select username, password, 1 from users where username=?")
                .authoritiesByUsernameQuery(
                        "select u.username, r.name from users_roles ur, users u, role r where u.username = ? and ur.users_id = u.id and ur.role_id = r.id")
                .passwordEncoder(bCryptPasswordEncoder);
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        System.out.println("setting cors configuration");
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.applyPermitDefaultValues();
        source.registerCorsConfiguration("/**", configuration);

        return source;
    }

}

WebConfig.java

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        AntPathMatcher matcher = new AntPathMatcher();
        matcher.setCaseSensitive(false);
        configurer.setPathMatcher(matcher);
    }
}

WHAT I'VE TRIED

tried as @Knox suggested, but still couldn´t make it work.

  1. not specifying allowedOrigins breaks the connection between frontend and backend on HOST machine (CORS ‘Access-Control-Allow-Origin’ missing), but from the outside it just shows the same as allways (CORS request did not succeed).
@Bean
    CorsConfigurationSource corsConfigurationSource() {
        System.out.println("setting cors configuration");
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration configuration = new CorsConfiguration();
        //configuration.applyPermitDefaultValues();
        //configuration.allowedOrigins("*");
        source.registerCorsConfiguration("/**", configuration);

        return source;
    }

enter image description here

  1. Swapping my WebConfig.java with the one provided by @Knox, everything works on HOST, still (CORS request did not succeed) from the outside

enter image description here

EDIT 2 (24/05/2022)

Just noticed my frontend container (React) is not responding to changes... my guess is the URL i've changed many times was never getting updated on docker compose restart. So changing URL from localhost:8080 to myip:8080 might fix it if i can get the container to reload.

fetch(URL + '/api/account/login', {

Dockerfile client

FROM node:8

WORKDIR /usr/scr/app
COPY package*.json ./

RUN npm install
COPY . .

CMD ["npm", "start"]

Docker-compose.yml

  client:
    build: ./client
    ports:
      - 3333:3000
    volumes:
      - ./frontend:/usr/src/app
      - /usr/src/app/node_modules
    networks:
      - network_backend



like image 815
zemmsoares Avatar asked Oct 21 '25 17:10

zemmsoares


1 Answers

Here is your error

Failed to load resource: net::ERR_CONNECTION_REFUSED localhost:8080/api/account/login:1 TypeError: Failed to fetch

In react you have configured the URL with which the frontend will call the backend server. In that configuration you have wrongly configured the url as localhost:8080.

The React Frontend normally runs in the clients browser (If you don't have it configured otherwise) which I suppose is the case also here.

So when the browser of the client tries to call localhost:8080 it is able to do so when the client sits on the same machine where the backend server runs, as the same machine understands that the backend server runs on localhost:8080.

But when the client sits to some other machine inside the network, the Frontend (clients browser) tries again to call localhost:8080 but that machine does not have locally the server running. Therefore the error.

Solution

Configure the React application code, so that it uses as address to reach the backend not localhost:8080 but some address that is known from all hosts in the network, meaning the ip address of the machine where the server runs. Could be 192.168.1.x:8080 as you say that this is reachable from some user outside of the machine where the server runs.

like image 129
Panagiotis Bougioukos Avatar answered Oct 23 '25 05:10

Panagiotis Bougioukos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!