Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

Duvida com Servidor Rest

Fiz um simples login e que vai em um servidor Rest Java e retorna o usuário.

Login.ts

constructor(public navCtrl: NavController, 
              public navParams: NavParams,
              private _alertCtrl: AlertController,
              private _usuarioSerice: UsuarioServiceProvider              
  ) {
  }

  efetuaLogin(){

    let usuario: Usuario = {
      id: '',
      nome: '',
      email: this.email,
      senha: this.senha,
      dataNasc: '',
      urlFoto: '',
    }  


    this._usuarioSerice.efetuaLogin(usuario)
    .subscribe(
      (usuario: Usuario) => {
        this.navCtrl.setRoot(HomePage);
        } ,
      () => {

        this._alertCtrl.create({
          title: 'Falha no Login',
          subTitle: 'Email ou senha incorretos, verifique!',
          buttons: [{
            text: 'Ok'
          }]
        }).present();

      }
    );

Serviço

 constructor(public _http: HttpClient, 
              private _api: ApiServiceProvider) {
  }

  efetuaLogin(usuario: Usuario) {
     return this._http.post<Usuario>('http://localhost:8080/tennisRanking/service/usuarios/logon', JSON.stringify(usuario))
        .do( (usuario: Usuario ) => this._usuarioLogado = usuario );
  }

e dá como Unsupported Media Type e Connection_refused

Detalhe, uso o Restlet Client Google e funciona normalmente o serviço Rest.

Como não consigo colocar imagem aqui, irei descrever os dados preenchidos no teste

Method Post "http://localhost:8080/tennisRanking/service/usuarios/logon"

Em Headers

Content-type: application/json

Body - Um Json

[{"email" : xxxx, "senha": xxx }]

Executo e funciona normalmente....

O que estou fazendo errado no Ionic ????

8 respostas

Boa noite, Andre! Como vai?

O problema está acontecendo pq vc está mandando um tipo de dado não suportado pelo seu serviço, como o próprio log já deixa claro: Unsupported Media Type.

Como visto durante o curso, vc deve executar o método post() do HttpCliet dessa forma:

efetuaLogin(email: string, senha: string): Observable<Usuario> {

    return this._http
                .post<Usuario>(`${this._url}/api/login`, { email, senha });
}

Repare que o segundo parâmetro é o próprio objeto que queremos enviar ao servidor e por trás dos panos o HttpClient irá se encarregar de transformá-lo em um JSON!

Grande abraço e bons estudos, meu aluno!

Boa noite, obrigado pela resposta

Então, como achei que estava fazendo errado, peguei o projeto final para verificar... De cara vejo uma diferença o Observable< Usuario > que não constava em seu projeto e esta até feito com o ip 192.168.0.59

E em sua resposta anterior tem este Observable

efetuaLogin(email: string, senha: string): Observable<Usuario> {

    return this._http
                .post<Usuario>(`${this._url}/api/login`, { email, senha });
}

E tinha tentado com apenas o email e senha e depois tentei como um objeto completo da interface e ambos nao funciona, porem, meu rest aceita os dois tipos e testado

Pós resposta tentei de outras formas, são:

Com Headers e sem Observable

 efetuaLogin(email: string,senha: string) {
  return this._http.post<Usuario>(this._api.url  + '/usuarios/logon', {email, senha}, {headers: {'Content-Type': 'application/json'}})
      .do( (usuario: Usuario ) => this._usuarioLogado = usuario );
 }

Sem Headers e sem Observable

 efetuaLogin(email: string,senha: string) {
  return this._http.post<Usuario>(this._api.url  + '/usuarios/logon', {email, senha})
      .do( (usuario: Usuario ) => this._usuarioLogado = usuario );
 }

Sem Headers e COM Observable

 efetuaLogin(email: string,senha: string): Observable<Usuario> {
  return this._http.post<Usuario>(this._api.url  + '/usuarios/logon', {email, senha})
      .do( (usuario: Usuario ) => this._usuarioLogado = usuario );
 }

E por final o mesmo acima com Headers também

Em todos casos, apresenta a mesma resposta:

Failed to load http://localhost:8080/tennisRanking/service/usuarios/logon: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access.

Obrigado

Andre

solução!

Opa, André! Como vai?

O :Observable<Usuario> que vc viu no meu código não é obrigatório! Esse é apenas um recurso do Typescript para deixarmos explícito o tipo de retorno do método! Ou seja, o fato de vc não ter acrescentado essa informação não é o problema do seu código, tanto é verdade que eu nem ao menos citei essa diferença na minha resposta.

Veja que o foco da resposta que te dei foi em relação a como vc estava passando o segundo parâmetro do método post() da classe HttpClient.

Em outras palavras, só pra deixar claro, os dois trechos de código a seguir estão corretos! A diferença entre eles é que o primeiro deixa explícito o retorno do método e o segundo não. No entanto, no mundo Typescript o ideal é que vc sempre deixe explícito os tipos de suas variáveis e retornos de métodos para poder usar o autocomplete e o type checking (assunto tratado com mais profundidade nos cursos sobre Typescript aqui na Alura).

efetuaLogin(email: string, senha: string): Observable<Usuario> {

    return this._http
                .post<Usuario>(`${this._url}/api/login`, { email, senha });
}
efetuaLogin(email: string, senha: string) {

    return this._http
                .post<Usuario>(`${this._url}/api/login`, { email, senha });
}

Entendido até aqui?

Agora, sobre o novo erro

Failed to load http://localhost:8080/tennisRanking/service/usuarios/logon: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access.

É um famoso erro que ocorre devido à política de segurança do protocolo HTTP para compartilhamento de recursos entre origens diferentes (ou CORS, vc pode encontrar mais detalhes sobre essa política de segunça aqui).

Basicamente, a sua requisição agora está chegando na sua API mas ela não está apta a receber requisições externas a ela. Daí vc terá que pesquisar para saber como configurar ela para permitir o acesso a recursos de modo externo. Isso depende da linguagem que vc está utilizando. Por exemplo, a API do curso de Ionic 3 foi escrita em Node, então foi preciso fazer isso aqui:

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

app.use(cors());  // tirando essa linha a API não receberia requisições externas e daria o mesmo problema.

Pegou a ideia?

ATENÇÃO ESTE CODIGO JAVA ESTAVA ERRADO NA PRIMEIRA VEZ E FOI AJUSTADO PARA FUNCIONAR CORRETAMENTE, ASSIM, TODOS EXEMPLOS DO PROFESSOR E AGORA A PARTE JAVA ESTA CORRETA, VOLTEI E AJUSTEI PARA TER ALGO PARA ALGUEM

Eu ate entendi, só não compreendo o porque continua... Implementei o Cors conforme instruções que vi em vários sites, olha meu retorno via teste post E na aplicação Ionic continua o erro.

POST /tennisRanking/service/usuarios/logon HTTP/1.1
Content-Length: 50
Host: localhost:8080
Content-Type: application/json

[{"email":andre.jrocha@uol.com.br,"senha":123456}]

HTTP/1.1 200 OK
X-Powered-By: Undertow/1
Access-Control-Allow-Headers: origin, content-type, accept, authorization
Server: WildFly/10
Date: Sun, 15 Apr 2018 22:00:33 GMT
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Type: application/json;charset=UTF-8
Content-Length: 109
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, HEAD
Acess-Control-Allow-Origin: *

{"id":1,"nome":"Andre Rocha","email":"andre@uol.com.br","senha":"123456","dataNasc":null,"urlFoto":""}
Viu que tem "Access-Control-Allow-Origin: *

Vi nos foruns de Java Rest aqui e um rapaz tinha o problema similar e resolveu como fiz...

Meus Códigos Java

        @POST
    @Path("/logon")
    @Consumes("application/json; charset=UTF-8")
    @Produces("application/json; charset=UTF-8")
    public Response logon(String jsonString) {


        GSon gson = new Gson();
        // Crie uma Classe que receba exatamente o conteudo de seu Json e não esqueça dos Getter Setter.
        UsuarioTo res = gson.fromJson(jsonString, UsuarioTo.class);
        // Essa classe UsuarioTO só contem email e senha

        Usuario usu = new Usuario();
        try {


            usu = dao.buscaUsuarioEmail(res.getEmail(), res.getSenha());
            return Response.ok()
                    .header("Acess-Control-Allow-Origin", "*")
                    .entity(usu)
                    .build();


        } catch (Exception e) {
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                    .header("Acess-Control-Allow-Origin", "*")
                    .entity(e.getStackTrace().toString()).build();
        }

    }
import java.io.IOException;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;

@Provider
public class CorsFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
            throws IOException {
        responseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
        responseContext.getHeaders().add("Access-Control-Allow-Credentials", "true");
        responseContext.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
        responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
    }
}

LOGIN.TS

efetuaLogin(){

   this._usuarioSerice.efetuaLogin(this.email, this.senha)
    .subscribe(
      (usuario: Usuario) => {
        this.navCtrl.setRoot(HomePage);
        } ,
      () => {

        this._alertCtrl.create({
          title: 'Falha no Login',
          subTitle: 'Email ou senha incorretos, verifique!',
          buttons: [{
            text: 'Ok'
          }]
        }).present();

      }
    );



  }

Service

efetuaLogin(email: string,senha: string) : Observable<Usuario> {

      return this._http.post<Usuario>('http://localhost:8080/tennisRanking/service/usuarios/logon', { email, senha})
          .do( (usuario: Usuario ) => this._usuarioLogado = usuario );
     }

Bom, se quiser fechar o tópico...acho que pode confundir os demais... O curso de Rest da Alura não fala nada de Cors, então, terei que buscar conhecimento fora e os comentários nesse tópico iriam atrapalhar. E usam Grizzly e não Jersey, mesmo assim não há Cors.

Uma pena, porque fico no projeto no Curso, meu intuito era agregar Java e Ionic, que seria uma necessidade mais imediata.

Um serviço Rest tem que prever justamente o Mobile e não poderia ter passado em branco no curso e na época que fiz iria usar PrimeFaces Mobile e por isso não senti necessidade.

Obrigado

Opa, André! O seu filtro aparentemente está correto, mas talvez esteja faltando alguma configuração no seu projeto. No entanto, como esse erro agora é relativo ao seu projeto Java, para que o fórum fique mais organizado, aconselho vc a criar um tópico na seção de JAX-RS sobre esse assunto dando maiores detalhes lá sobre como vc está desenvolvendo o seu projeto para que o pessoal possa te ajudar!

Fechado, meu aluno? Faz isso que te aconselhei que haverá uma boa chance de resolver tudo aqui no fórum mesmo!

Grande abraço!

P.S.: Em todo caso, eu fiz um projeto em Java usando o Jersey para aceitar a requisição de login já com o CORS configurado!

Segue o link para download do projeto (link válido por 30 dias): https://ufile.io/1rnxs

Com a API no ar, acessei ela assim no Ionic:

this._http.post(`http://localhost:8080/aluracar-webservice-java/api/user/login`, {})
          .subscribe(
            () => console.log('login feito!'),
            (error) => console.log(error)
          );

Vc verá que a API será acionada corretamente sem o erro que vc estava obtendo antes.

Grande abraço, meu aluno!

Obrigado.

Eu acabei lendo algumas coisas e percebi que não era nada de Cors e quando passei o teste na primeira vez, foi um teste errado e ai apresentou aquele erro com Cors, Apesar de apresentar o erro, não era.

Eu tentei fazer uma autenticação "hibrida" mesmo que ele me enviasse campos desnecessário , pegaria o que fosse necessário ao serviço e o erro no final era isso. E claro, quando coloquei o headers (faltava no projeto) era para funcionar e ai o erro era o Json porque deixei sujeira.

A classe de conversão Json que usei nao estava interpretando corretamente, então, ajustei o meu código descrito acima que já esta testado e funcionando. Assim se alguém quiser usar Java, Ionic e Rest Jersey tem um exemplo completo e funcional.

Deixei um comentario no Post e ajustei corretamente