0

What I want to do: Frontend sends username and password to the backend. Backend checks it, generates a random string, and sends back that string to the frontend. Frontend saves that string to localStorage.

In the backend:

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public String login(String credentials){
    return this.service.login(credentials);

}

this.service.login returns a string if username and password in credentials is OK or returns null if not.

In the frontend:

public login(username: string, password: string ){
return this.http.post<string>(this.authUrl, JSON.stringify({username: username, password: password}), this.getHeaders())
.pipe(
  tap(
    (token:string) => {
      if(token){
        localStorage.setItem('accessToken',token);
        console.log(`Successful login for username =${username} with password=${password} and token=${token}` );
      } else {
        console.log(`Login failed for username =${username} with password=${password} and token=${token}`);
      }
    }
  )
);

}

getHeaders(): {headers: HttpHeaders } {
const httpOptions = {
  headers: new HttpHeaders(
    {
      'Content-type': 'application/json',
      'responseType': 'text'
    }
  )     
};
return httpOptions;

}

If I try to login with wrong username and password, this gets logged: Login failed for username =something with password=something and token=null So the returning null part works, But if I send the correct username and password, I get this error:

ERROR
HttpErrorResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: "http://localhost:8080/login", ok: false, …}
error: {error: SyntaxError: Unexpected token M in JSON at position 0 at JSON.parse (<anonymous>) at XMLHtt…, text: "MTMyOTUz"}
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
message: "Http failure during parsing for http://localhost:8080/login"
name: "HttpErrorResponse"
ok: false
status: 200
statusText: "OK"
url: "http://localhost:8080/login"
__proto__: HttpResponseBase

So it has some JSON.parse problem? Does it expect a JSON so doesn't know what to do with a string? What's a solution to this?

cheesy
  • 89
  • 1
  • 1
  • 5
  • This might help: https://stackoverflow.com/questions/7487869/is-this-simple-string-considered-valid-json – MikeOne Oct 11 '19 at 14:08
  • Does your other routes work fine ? Try to add `Accept: 'application/json'` to your headers. – Florian Oct 11 '19 at 14:13
  • Not sure what do you mean by other routes, but for example listing users is served by localhost:8080/users and it works fine. I'll try adding that to the headers – cheesy Oct 11 '19 at 14:25
  • Adding that to the headers just threw me an error 406 (Not Acceptable) – cheesy Oct 11 '19 at 14:31
  • After a quick search, you may fix the issue by replacing your header responseType by : `'responseType': 'text' as 'json'` – Florian Oct 11 '19 at 14:40
  • I tried it but it did not help unfortunately, it gave the same error as originally. – cheesy Oct 11 '19 at 14:47
  • Your question is not related to Angular, I think that Angular is trying to parse your back-end response which is not a JSON. How are you returning the response from your API ? – Florian Oct 11 '19 at 14:55
  • I wanted to return a string, because I only wanted to return a single word so I thought that would be the easiest solution. – cheesy Oct 11 '19 at 15:16
  • Similar issue here, but I'm actually getting "406 OK"... really bizarre. No amount of tweaking in Angular's headers seems to fix it, and when I do the same request with wget it works fine. – Nyerguds Mar 04 '20 at 15:23

2 Answers2

0

Alright I didn't know how to get this work with string, so I ended up using json instead. So in this.service.login:

JsonObject tokenJson = new JsonObject();
tokenJson.addProperty("token", token);
return tokenJson;

then:

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public JsonObject login(String json){
    return this.service.login(json);
}

In the frontend changed return type from string to objectand get my token like this:

var tokenObject = JSON.parse(JSON.stringify(token));
localStorage.setItem('accessToken',tokenObject.token);
cheesy
  • 89
  • 1
  • 1
  • 5
0

By default httpclient parses json. For telling it that in return text will come as response you need to use the syntax below.

this.httpClient.request('GET', 'url, {responseType:'text'});

Aakash Garg
  • 10,649
  • 2
  • 7
  • 25