1.I can't setup a proper request, with useCredentials.Can anyone tell me what's wrong with the code?
import { Injectable } from '#angular/core';
import { Http, Response,Headers, RequestOptions } from '#angular/http';
import { Observable } from 'rxjs/Observable';
#Injectable ()
export class StructureRequestService {
result: Object;
constructor (private http: Http) {
2.use XHR object - I think the problem is here.
let _build = (<any> http)._backend._browserXHR.build;
(<any> http)._backend._browserXHR.build = () => {
let _xhr = _build();
_xhr.withCredentials = true;
return _xhr;
};
}
private myUrl = 'http://manny.herokuapp.com/audit/get/structure';
//create an http request
sendRequest() {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({
headers: headers
// , withCredentials: true
});
return this.http.post(this.myUrl,options)
.map((res: Response) => res.json())
.subscribe(res => {this.result = res;});
}
}
You are missing the post body parameter in your post request. It must be a string
return this.http.post(this.myUrl, body, options)
Body
Despite the content type being specified as JSON, the POST body must actually be a string. Hence, we explicitly encode the JSON hero content before passing it in as the body argument.
ref: https://angular.io/docs/ts/latest/guide/server-communication.html
Related
I'm trying to stream the html response in Deno but can't quite figure it out.
Doing it from a Service Worker on the front end looks like this:
async function streamResponse(html: {start: (s: string) => Promise<void>}) {
const encoder = new TextEncoder()
const stream = new ReadableStream({
async start(controller : ReadableStreamDefaultController<any>) {
const send = (item: string) => controller.enqueue(encoder.encode(item))
await html.start(send)
controller.close()
}
})
return new Response(stream, { headers: { "content-type": "text/html; charset=utf-8" }})
}
When I do something similar to that in Deno (req.respond({body: stream, headers})) it says that the body can't be of the type ReadableStream. I know there is some way to do this. I just can't figure it out. What am I missing? I looked in multiple places trying to understand how it is done but I haven't found any good example yet.
Figured it out. I need to use Deno.Buffer as the writer and then bring in BufReader to wrap the writer.
import { BufReader } from "https://deno.land/std#0.79.0/io/bufio.ts"
import { ServerRequest } from "https://deno.land/std#0.79.0/http/server.ts"
import { HTML } from "./html.ts"
var headers = new Headers({
"Content-Type": "text/html"
})
const encoder = new TextEncoder()
export async function toHTML(req: ServerRequest, html: Promise<HTML>) {
var buffer = new Deno.Buffer()
var body = new BufReader(buffer)
var h = await html
req.respond({body, headers})
await h.start((item: string) => buffer.write(encoder.encode(item)))
}
I'm struggling to figure out why the response I get from my API isn't mapping to an object that I have in typescript.
Here's the function in my service that calls the API:
register(user: IUser): Observable<IUser> {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
var options = new RequestOptions({
headers: headers,
url: this._registerUrl,
body: JSON.stringify(user)
});
return this._http.post(this._registerUrl, { user }, options)
.map((res: Response) => res.json() as IUser)
.catch(this.handleError);
}
This is the function that calls the service:
register(): void {
let user: IUser = {
email: this.email,
username: this.username,
password: this.password
}
this._userService.register(user)
.subscribe(result => {
debugger;
if(result.errorCode > 0)
this.handleError(result.errorCode);
else {
localStorage.setItem('userId', result.userId.toString());
localStorage.setItem('username', result.username.toString());
localStorage.setItem('email', result.email.toString());
}
});
}
The object that I am returning from the API matches the object that I have in the frontend. It is returning the data and I can see it in the body of my response. All of the data is right, but it's in the body and is not turning it into an IUser object.
Does anybody have any ideas? Thanks.
EDIT
This is what the response object looks like when it comes back from the service.
I have a backend API, which as shown in this POSTMAN screenshot is working.
Here is my service:
getComments(line: string, department: string, startTime?: number, endTime?: number): Observable<Array<IComments>> {
let headers = new Headers(
{
'Content-Type': 'application/x-www-form-urlencoded',
'line': line,
'cell': department,
'start': new Date(),
'end': ago(24, "hours")
});
let options = new RequestOptions({ headers: headers });
return this.http.get('api/data/comments', options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
and this is what my component contains:
this.dataService.getComments('604', 'powders').forEach(result => {
console.log('Res: ' + JSON.stringify(result));
that.comments = result;
});
However, all I get in the console is:
Res: {}
Why is the data not being returned, as it is in postman?
Update:
and if I console.log(body) in extractData, then I get:
Object {result: "COMMENTS604"}
In extractData you are returning body.data, but since the property is named result, I think you meant to return body.result
I have the following code which is a simple service that goes back to the server to fetch some data:
import { Injectable } from '#angular/core';
import { Action } from '../shared';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { Authenticated } from '../authenticated';
import 'rxjs/Rx';
#Injectable()
export class ActionsService {
private url = 'http://localhost/api/actions';
constructor(private http: Http, private authenticated : Authenticated) {}
getActions(search:string): Observable<Action[]> {
let options = this.getOptions(false);
let queryString = `?page=1&size=10&search=${search}`;
return this.http.get(`${this.url + queryString}`, options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(response: Response) {
let body = response.json();
return body || { };
}
private handleError (error: any) {
let errMsg = (error.message) ? error.message : error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
if (error.status == 403) {
this.authenticated.logout();
}
return Observable.throw(errMsg);
}
private getOptions(addContentType: boolean) : RequestOptions {
let headers = new Headers();
if (addContentType) {
headers.append('Content-Type', 'application/json');
}
let authToken = JSON.parse(localStorage.getItem('auth_token'));
headers.append('Authorization', `Bearer ${authToken.access_token}`);
return new RequestOptions({ headers: headers });
}
}
Everything works as expected except for handleError. As soon as getActions receives an error from the server it goes into the this.handleError method which again works fine up until the section where this.authenticated.logout() should be called. this.autenticated is undefined and I am not sure if it is because "this" is referring to another object or if ActionSerivce's local variables are made null when and http exception occurs. The authenticated local variable is properly injected (I did a console.log in the constructor and it was there).
The problem is that you are not binding the this context in your callback function. You should declare your http call like this for example:
return this.http.get(`${this.url + queryString}`, options)
.map(this.extractData.bind(this)) //bind
.catch(this.handleError.bind(this)); //bind
Another option could be to pass an anonymous function and call the callback from there:
return this.http.get(`${this.url + queryString}`, options)
.map((result) => { return this.extractData(result)})
.catch((result) => { return this.handleError(result}));
And yet another option is to declare your callback functions a little differently, you can keep your http call the way you had it before:
private extractData: Function = (response: Response): any => {
let body = response.json();
return body || { };
}
private handleError: Function = (error: any): any => {
//...
}
I have a little problem with my Angular2 app. I want to get some data from server for my user login, but my code is going ahead and I have a lot of bugs with it. I want to wait for answer from server, then do something with my data.
This is my code:
import { Injectable } from '#angular/core';
import { Http, Response, Headers } from '#angular/http';
import { Observable } from 'rxjs/Rx';
import { User } from './user';
#Injectable()
export class UserService {
public usersTmp: Array<Object> = new Array<Object>();
public users: Array<User>;
public user: User = new User();
public noteToSend;
constructor(private http: Http) { }
getUsers() {
var headers = new Headers();
headers.append('Accept', 'q=0.8;application/json;q=0.9');
this.http.get('/AngularApp/api/users', { headers: headers })
.map((res: Response) => res.json())
.subscribe(
data => {
console.log(data);
this.usersTmp = data;
},
err => console.error(err),
() => console.log('done')
);
this.users = new Array<User>();
for (var i = 0; i < this.usersTmp.length; i++) {
this.user = new User();
this.user.id = this.usersTmp[i]["userId"];
this.user.name = this.usersTmp[i]["userName"];
this.user.email = this.usersTmp[i]["userEmail"];
this.user.pass = this.usersTmp[i]["userPassword"];
this.users.push(this.user);
}
return this.users;
}
As I noticed my code is going to the for loop until I get answer from server, so I return just empty array. Anyone can help me with that?
In the service, you should return the Observable that your component can subscribe to. It cannot work they way you do it due to the asynchronous mode of the get request.
As a proposal, your service could look similar to this
getUsers() {
let headers = new Headers();
headers.append('Accept', 'q=0.8;application/json;q=0.9');
return this.http.get('/AngularApp/api/users', { headers: headers })
.map((res: Response) => res.json());
}
And the relevant part of your component like this:
constructor(private userService:UserService) {
this.userService.getUsers().subscribe(
data => this.iterateOverUsers(data));
}
iterateOverUsers(data) {
// here comes your for loop
}