<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chrystian do Espirito Santo Nascimento</title>
    <description>The latest articles on DEV Community by Chrystian do Espirito Santo Nascimento (@01chrystian).</description>
    <link>https://dev.to/01chrystian</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2914933%2Fcc284554-5498-4149-9281-5c6fc70070ae.jpeg</url>
      <title>DEV Community: Chrystian do Espirito Santo Nascimento</title>
      <link>https://dev.to/01chrystian</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/01chrystian"/>
    <language>en</language>
    <item>
      <title>Problema com CORS e WebSocket no Angular</title>
      <dc:creator>Chrystian do Espirito Santo Nascimento</dc:creator>
      <pubDate>Wed, 05 Mar 2025 18:58:05 +0000</pubDate>
      <link>https://dev.to/01chrystian/problema-com-cors-e-websocket-no-angular-16nn</link>
      <guid>https://dev.to/01chrystian/problema-com-cors-e-websocket-no-angular-16nn</guid>
      <description>&lt;p&gt;Olá, pessoal! Estou enfrentando um problema ao tentar fazer uma requisição de WebSocket no meu projeto Angular. A aplicação Angular está rodando no endereço &lt;a href="http://localhost:4200/" rel="noopener noreferrer"&gt;http://localhost:4200/&lt;/a&gt; e o servidor WebSocket está em &lt;a href="http://localhost:8080/" rel="noopener noreferrer"&gt;http://localhost:8080/&lt;/a&gt;. Quando tento estabelecer a conexão, recebo o seguinte &lt;/p&gt;

&lt;p&gt;erro:&lt;br&gt;
Access to XMLHttpRequest at '&lt;a href="http://localhost:8080/ws/info?t=1741192064562" rel="noopener noreferrer"&gt;http://localhost:8080/ws/info?t=1741192064562&lt;/a&gt;' from origin '&lt;a href="http://localhost:4200/" rel="noopener noreferrer"&gt;http://localhost:4200/&lt;/a&gt;' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.&lt;/p&gt;

&lt;p&gt;Além disso, o seguinte erro é registrado:&lt;br&gt;
GET &lt;a href="http://localhost:8080/ws/info?t=1741192064562" rel="noopener noreferrer"&gt;http://localhost:8080/ws/info?t=1741192064562&lt;/a&gt; net::ERR_FAILED 404 (Not Found)&lt;/p&gt;

&lt;p&gt;Código que estou utilizando no backend (Spring Boot)&lt;/p&gt;

&lt;p&gt;WebSocketConfig.java (Configuração do WebSocket)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Configuration
@EnableWebSocketMessageBroker
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    private final String allowedOrigin = "http://localhost:4200";

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws") // Endpoint WebSocket
          .setAllowedOrigins(allowedOrigin)  // Permite origens específicas
                .withSockJS(); // Permite fallback para SockJS
    }

    @Override
    public void addArgumentResolvers(List&amp;lt;HandlerMethodArgumentResolver&amp;gt; argumentResolvers) {
        argumentResolvers.add(new WebSocketAuthenticationPrincipalArgumentResolver());
    }

    @Override
    public boolean configureMessageConverters(List&amp;lt;MessageConverter&amp;gt; messageConverters) {
        DefaultContentTypeResolver resolver = new DefaultContentTypeResolver();
        resolver.setDefaultMimeType(MediaType.APPLICATION_JSON);
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setObjectMapper(new ObjectMapper());
        converter.setContentTypeResolver(resolver);
        messageConverters.add(converter);
        return false;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SecurityConfig.java (Configuração de segurança com CORS)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @SuppressWarnings("unused")
    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Autowired
    SecurityFilter securityFilter;

    @SuppressWarnings("removal")
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -&amp;gt; csrf.disable())
                .sessionManagement(session -&amp;gt; session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(authorize -&amp;gt; authorize
                        .requestMatchers(HttpMethod.POST, "/auth/login").permitAll()
                        .requestMatchers(HttpMethod.POST, "/auth/register").permitAll()
                        .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()  // Permite requisições OPTIONS
                        .requestMatchers("/ws/**").permitAll()  // Permite WebSocket
                        .anyRequest().authenticated()
                )
                .addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class)
                .cors().and();
        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CorsConfig.java (Configuração do CORS)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            .allowedOrigins("http://localhost:4200")  // Apenas Angular pode acessar
            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // Métodos permitidos
            .allowedHeaders("*")  // Permite qualquer cabeçalho
            .allowCredentials(true); // Permite envio de cookies/tokens
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Código no frontend (Angular)&lt;/p&gt;

&lt;p&gt;WebSocketService.ts (Serviço WebSocket)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from '@angular/core';
import SockJS from 'sockjs-client';
import { Client, over } from '@stomp/stompjs';

@Injectable({
  providedIn: 'root',
})
export class WebSocketService {
  private stompClient!: Client;
  private socketUrl = 'http://localhost:8080/ws'; // URL do WebSocket backend

  disconnect(): void {
    if (this.stompClient &amp;amp;&amp;amp; this.stompClient.connected) {
      this.stompClient.disconnect(() =&amp;gt; {
        console.log('Desconectado do WebSocket');
      });
    }
  }
  // Conectar ao WebSocket
  connect(callback: (message: any) =&amp;gt; void): void {
    const socket = new SockJS(this.socketUrl);
    this.stompClient = over(socket);

    this.stompClient.connect({'Authorization:' : 'Bearer ' + localStorage.getItem('auth-token')}, () =&amp;gt; {
      console.log('Conectado ao WebSocket');
      // Assina o tópico de atualizações
      this.stompClient.subscribe('/topic/updates', (message) =&amp;gt; {
        callback(JSON.parse(message.body)); // Processa a mensagem recebida
      });
    });
  }

  sendMessage(content: string): void {
    if (this.stompClient &amp;amp;&amp;amp; this.stompClient.connected) {
      const chatMessage = { content };
      this.stompClient.send('/app/message', {}, JSON.stringify(chatMessage));
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WebSocketComponent.ts (Componente Angular para interação com o WebSocket)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, OnDestroy, OnInit } from '@angular/core';
import { WebSocketService } from '../../core/service/web-socket.service';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-web-socket',
  imports: [CommonModule],
  templateUrl: './web-socket.component.html',
  styleUrl: './web-socket.component.css'
})
export class WebsocketComponent implements OnInit, OnDestroy {
  messages: string[] = [];

  constructor(private webSocketService: WebSocketService) {}

  ngOnInit(): void {
    this.webSocketService.connect((message: string) =&amp;gt; {
      this.messages.push(message);
    });
  }

  sendMessage(): void {
    this.webSocketService.sendMessage('Olá, WebSocket!');
  }

  ngOnDestroy(): void {
    this.webSocketService.disconnect();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>angular</category>
      <category>websockets</category>
      <category>java</category>
      <category>cors</category>
    </item>
  </channel>
</rss>
