Angular 7 HttpClient post can not parse large request body? - json

Does angular HttpClient have limit on request body size?
I was doing an angular project that consumes a rest API. The API is simple, it's just replace a JSON file whenever the API endpoint to the file hits using POST method, with new JSON object as the request body.
The code runs well if the new JSON object is small and only have some nodes, However the code returns an error with status code 400 and error message "Error when parsing request" when i'm trying to send big object. Does the error caused by the big object or am i doing it incorrectly?
Last time it returns error is when i tried to send big JSON file with ~1.5MB size, the JSON object seems to be valid as several online json formatters report it as a valid json object.
I'm sorry if i didn't explain my problem well, as i'm not native english user, and i'm also quite new in angular world. Thanks
import { HttpClient, HttpHeaders, HttpErrorResponse } from "#angular/common/http";
import { take, catchError } from "rxjs/operators";
import { throwError, Observable } from "rxjs";
import { Injectable } from "#angular/core";
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Accept': 'application/json',
'Cache-Control': 'no-cache',
'Access-Control-Allow-Origin': '*'
});
#Injectable()
export class configService {
private _url = 'http://some-api-endpoint/';
constructor(private http:HttpClient) { }
private _save(data):Promise<any> {
return this.http.post(this._url, data, { headers, responseType: 'text', observe:'response' })
.pipe(
take(1),
catchError(err => this._handleError(err))
)
.toPromise();
}
public async updateConfigFile(data): Promise<any> {
try {
const json = JSON.stringify(data, null, 2);
const update = await this._save(json);
if(update.status === 201) {
return {
success: true,
data: update
}
} else {
return {
success: false,
error: update
}
}
} catch(err) {
return {
success: false,
error: err.message
}
}
}
private _handleError(error: HttpErrorResponse): Observable<never>{
let errObj = {};
if(error.error instanceof ErrorEvent) {
const err = error.error
console.warn('An client-side error occured:', {err});
errObj = {
status: 'internal error',
message: error.error.message
}
} else {
console.warn(`Backend returned code ${error.status} `, {error});
errObj = {
status: error.status,
message: error.error
}
}
return throwError(errObj);
}
}

Related

Next JS Error serializing `.dehydratedState.queries[0].state.data.config.adapter` returned from `getServerSideProps

I am trying to use react-query to fetch data in getServerSideProps in Next JS but I keep getting this weird error:
Error: Error serializing `.dehydratedState.queries[0].state.data.config.adapter` returned from `getServerSideProps` in "/auth/google/callback".
Reason: `function` cannot be serialized as JSON. Please only return JSON serializable data types.
Here is my code:
// Packages
import { useRouter } from 'next/router'
import { dehydrate, QueryClient, useQuery } from 'react-query';
// APIs
import { completeGoogleAuth } from '../../../hooks/auth';
export async function getServerSideProps(context) {
const queryClient = new QueryClient()
await queryClient.prefetchQuery('completeGoogleAuth', () => completeGoogleAuth(context.query.code));
return {
props: {
dehydratedState: dehydrate(queryClient),
},
}
}
export default function Callback() {
const router = useRouter();
const { data } = useQuery('completeGoogleAuth', () => completeGoogleAuth(router.query.code))
return (
<>
Loading
</>
)
}
I have tried to use JSON.stringify(dehydrate(queryClient)) and also used JSON.parse(JSON.stringify(dehydrate(queryClient))) but none of them worked.
What can I do?
I stumbled across the same error just today, JSON.stringify(dehydrate(queryClient)) or serializing dehydrate(queryClient) by any means won't really work as the object your completeGoogleAuth function is returning has function values in the key-value pairs, here's a picture of the config object.
And as you know, functions can't be JSON serialized as straightforwardly. Now, what I assume you used(or what I did too) for the completeGoogleAuth fetcher function is use Axios as your API client library. I have found that Axios returns objects that can't be JSON serialized. As a solution, I have just used the native JavaScript fetch() API to get API data and the haven't faced any issues since then.
Here's my fetcher function:
export const getScholarshipInfoSSR = async (token) => {
const response = await fetch(
process.env.NEXT_PUBLIC_API_BASE_URL + portalRoutes.getScholarshipInfo,
{
headers: { Authorization: `JWT ${token}` },
}
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json().then((data) => ({ data }));
};
Here's the prefetched useQuery invocation:
await queryClient.prefetchQuery("portal", () =>
getScholarshipInfoSSR(token)
);

Angular Unexpected token c in JSON at position 0 at JSON.parse when expecting a string

I am not sure what I am doing wrong here.
I am trying to use the checkout facility for stripe using this documentation: https://stripe.com/docs/payments/checkout/accept-a-payment
I have configured my API to just return the checkoutid as a string.
The Angular service just calls the controller. When I run my code I actually get a nice 200 response and I can see the checkout id in the response body, but Angular throws an error:
SyntaxError: Unexpected token c in JSON at position 0 at JSON.parse () at XMLHttpRequest.onLoad (https://127.0.0.1:4200/vendor.js:18780:51) at ZoneDelegate.invokeTask
The service looks like this:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { map } from 'rxjs/operators';
import { environment } from '#environments/environment';
#Injectable({
providedIn: 'root',
})
export class StripeService {
private endpoint: string = 'stripe';
constructor(private http: HttpClient) {}
checkout(priceId: string) {
return this.http
.get<string>(`${environment.apiUrl}/${this.endpoint}/${priceId}`)
.pipe(
map((response) => {
console.log(response);
return response;
})
);
}
}
and I am invoking it like this:
this.stripeService
.checkout(this.button.priceId)
.subscribe((checkoutId: string) => {
console.log(checkoutId);
// this.stripe
// .redirectToCheckout({
// sessionId: checkoutId,
// })
// .then(function (result) {
// // If `redirectToCheckout` fails due to a browser or network
// // error, display the localized error message to your customer
// // using `result.error.message`.
// });
});
If I look in the network tab I can see this:
But the console actually shows this:
Does anyone have a scooby why?
Probably the response is a string and you haven't specified the response type. Try the following
this.http.get(
`${environment.apiUrl}/${this.endpoint}/${priceId}`,
{ responseType: 'text' }
)
Default response type is json.
It happened to me when my API return doesent match with my deserializable object on Angular. At first, try to check your returns entities

HttpClient.post is sucessful but not sending data to json

I am trying to store data from my angular app into a JSON. The JSON is stored within the assets folder of my app and I have the app on a server.
I am using HttpClient to POST data to the JSON. It says it is successful but it does not actually send the data.
This is my .ts:
import { HttpClient } from '#angular/common/http'
import { HttpHeaders } from '#angular/common/http'
export class OpscreenComponent implements OnInit {
constructor(private httpService: HttpClient ) { }
ngOnInit() {
var jsonpost = {
"testing": [
{
"anothertest":"here",
"anumber": 1
}
]
}
var headers = new HttpHeaders({
'Content-Type': 'application/json'
})
var options = { headers: headers }
this.httpService.post("http://servername/angularApp/assets/testing.json", jsonpost, options)
.subscribe(
data=> {
console.log("POST Request is Successful ", data )
},
error => {
console.log("Error ", error)
}
)
}
}
I get no error messages and the request is successful because it is logging POST Request is Successful null in the console.
The json is blank to start and after the POST success it is still blank (hence the null in the console.)
Why is it not posting the data to the JSON?
I am using httpClient for get so I know it is imported correctly.
this.httpService.request('POST', `${YourTestUri}`, { body: jsonpost, headers: headers }).pipe( switchMap( (response: any) => ... ) );
What you are trying to do is write files to disk, unfortunately, The HttpClient of Angular can't write files to disk. At least not with the classic implementation.
You probably prefer to add a server who can write to the disk, and your HttpClient will hit the server with the corresponding data.

Typescript Rest API POST call with JSON parameter

I'm trying to find a code example to send a POST request to a REST Api with a JSON as parameter and get the response and any exceptions / error codes in Typescript.
You could start with something like that
Service
export class MyService{
constructor(
private httpClient: HttpClient) {
}
getSomethingFromServer():Observable<any>{
return this.httpClient.get('you_request_url');
}
}
Component
constructor(
private myService: MyService) {
}
this.myService.getSomethingFromServer().subscribe(response => {
// do whatever you want with the response
}, error => {
// handle error here
// error.status to get the error code
});
First set the headers as follows, the "userIdAuthToken" should be the token returned from security service
this.httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.userIdAuthToken
})
};
Then make your request,
private _http: HttpClient // goes in constructor
let saveRequest = this._http.post<Project>(
this.apiUrl + '/project' + '/post',
JSON.stringify(data),
this.httpOptions);
saveRequest will be an observable so you need to subscribe to it in your component
//Final working code. You should maintain service for api call and call it from Component.ts
public post(a : string, data: string): Observable{
const options = new RequestOptions({
headers: this.getAuthorizedHeaders(),
responseType: ResponseContentType.Json,
withCredentials: false
});
return this.http.post(this.BASE_URL, JSON.stringify({ var: a, data: data}), options)
.map(this.handleData)
.catch(this.handleError);
}
Is a library will do the trick? Worth taking a look at node-fetch, fetch-as, make-fetch-happen, and what not.

HTTP Native Plugin (IONIC 3)

I'm trying to make a post request using the HTTP cordova plugin. However, for some reason, the JSON data consumed by the Server side is not being formatted correctly (json brakets). Could anyone help me please?
The import:
import { HTTP } from '#ionic-native/http';
The request implementation:
public sendData(sufix, json) {
return new Promise((resolve, reject) => {
this.http.post(URL+sufix, JSON.stringify(json), {'Content-Type': 'application/json'}).then(result => {
resolve(result.data);
}).catch(error => {
reject(error);
});
});
}
The json sended:
{name: 'Test'}
The content received by the server:
=%7B%22name%22%3A%22Test%22%7D
The server implementation:
#Path("/register")
public class RegisterEndPoint {
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response registerUser(UserDTO userDTO) {
// Create DAO for persistence
FactoryDAO factory = new FactoryDAO();
UserDAO userDAO = factory.getUserDAO();
// Create user to be persisted
if (!userDAO.userExist(userDTO.getEmail())) {
User user = new User();
user.setPassword(userDTO.getPassword());
user.setEmail(userDTO.getEmail());
user.setName(userDTO.getName());
userDAO.persist(user);
userDAO.commit();
return Response.status(200).build();
}
return Response.status(405).entity(new ErrorDTO("User already registered!")).build();
}
}
The problem seems to be in Native Plugin, so I've changed to the angular http solution, and it works fine. Follow below the solution which I've perform. Thanks everyone who helped me.
The imports required:
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Rx'
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/timeout';
AuthProvider:
public sendRequest(sufix, json) {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(URL+sufix, json, options)
.timeout(TIMEOUT_REQUEST*1000)
.do(this.logResponse)
.map(this.extractData)
.catch(this.handleError)
}
private logResponse(res: Response) {
console.log(res);
}
private extractData(res: Response) {
return res.json();
}
private handleError(res: Response | any) {
return Observable.throw(res.json().error || 'Fail to connect to the server');
}
Calling the AuthProvider:
this.authProvider.sendRequest('register', this.signup).subscribe((data) => {
console.log('Success!');
}, (error) => {
console.log(error);
});
Providers included in app.module.ts
import { HttpModule, JsonpModule } from '#angular/http';
can you please try sending the body without making it a string. you can send the JSON Object without stringify. Give it a try :)
**UPDATE
After sending this
{name: 'Test'}
If you are getting name = "test"
Why dont you try like this
var data = JSON.stringify(data);
var obj = {data:data};
//send the obj Object
So it will show as data = "{name:test}"
Now Parse it from the server. Try and let me know :)
if you are trying to make post request using HTTP then try sending request in this format.
let body = new FormData();
body.append('name', 'Test');
this.http.post(<url>,body);
Try and lemme know if it works for you.
Just add this.http.setDataSerializer(‘json’) before do the post