The specified content type was not found - Error 611 - NativeScript - nativescript

I'm following the step by step tutorial of NativeScript but I'm facing the following issue:
When I try to make a post request through my Angular service I get the following error:
JS: {"message":"The specified content type was not found.","errorCode":611}
My code looks pretty much the same as the one in the official docs from NativeScript:
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { User } from './user';
import { Config } from '../config';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
#Injectable()
export class UserService {
constructor(private _http: Http) { }
register(user: User): Observable<Response> {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
const url = `${Config.apiUrl}/Users`;
const body = JSON.stringify({
Username: user.email,
Email: user.email,
Password: user.password
});
return this._http.post(url, body, { headers })
.catch(this.handleErrors);
}
handleErrors(error: Response) {
console.error(JSON.stringify(error.json()));
return Observable.throw(error);
}
}
Component class:
signUp() {
this._user.register(this.user).subscribe(
() => {
alert('Your account has been successfully created.');
this.toggleDisplay();
},
() => {
// errors here...
alert('Unfortunately we were unable to create your account.');
}
);
}
Tested under Android and IOs, both throws the same error.
Isn't application/json the expected Content-Type in this case?
If I change the type I get another error saying that the type is missing or is invalid.
Can someone please point out what am I missing?

Related

How to upload file using nestjs-graphql-fastify server and how to test such feature?

I struggle to upload .csv file to nestjs-graphql-fastify server. Tried following code:
#Mutation(() => Boolean)
async createUsers(
#Args({ name: 'file', type: () => GraphQLUpload })
{ createReadStream, filename }: FileUpload,
): Promise<boolean> {
try {
// backend logic . . .
} catch {
return false;
}
return true;
}
but all I get when testing with postman is this response:
{
"statusCode": 415,
"code": "FST_ERR_CTP_INVALID_MEDIA_TYPE",
"error": "Unsupported Media Type",
"message": "Unsupported Media Type: multipart/form-data; boundary=--------------------------511769018912715357993837"
}
Developing with code-first approach.
Update: Tried to use fastify-multipart but issue still remains. What has changed is response in postman:
POST body missing, invalid Content-Type, or JSON object has no keys.
Found some answer's on Nestjs discord channel.
You had to do following changes:
main.ts
async function bootstrap() {
const adapter = new FastifyAdapter();
const fastify = adapter.getInstance();
fastify.addContentTypeParser('multipart', (request, done) => {
request.isMultipart = true;
done();
});
fastify.addHook('preValidation', async function (request: any, reply) {
if (!request.raw.isMultipart) {
return;
}
request.body = await processRequest(request.raw, reply.raw);
});
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
adapter,
);
await app.listen(apiServerPort, apiServerHost);
}
bootstrap();
upload.scalar.ts
import { Scalar } from '#nestjs/graphql';
import { GraphQLUpload } from 'graphql-upload';
#Scalar('Upload')
export class UploadGraphQLScalar {
protected parseValue(value) {
return GraphQLUpload.parseValue(value);
}
protected serialize(value) {
return GraphQLUpload.serialize(value);
}
protected parseLiteral(ast) {
return GraphQLUpload.parseLiteral(ast, ast.value);
}
}
users.resolver.ts
#Mutation(() => CreateUsersOutput, {name: 'createUsers'})
async createUsers(
#Args('input', new ValidationPipe()) input: CreateUsersInput,
#ReqUser() reqUser: RequestUser,
): Promise<CreateUsersOutput> {
return this.usersService.createUsers(input, reqUser);
}
create-shared.input.ts
#InputType()
export class DataObject {
#Field(() => UploadGraphQLScalar)
#Exclude()
public readonly csv?: Promise<FileUpload>;
}
#InputType()
#ArgsType()
export class CreateUsersInput {
#Field(() => DataObject)
public readonly data: DataObject;
}
Also, I want to mention you should not use global validation pipes (in my case they made files unreadable)
// app.useGlobalPipes(new ValidationPipe({ transform: true }));
You could use graphql-python/gql to try to upload a file:
from gql import Client, gql
from gql.transport.aiohttp import AIOHTTPTransport
transport = AIOHTTPTransport(url='YOUR_URL')
client = Client(transport=transport)
query = gql('''
mutation($file: Upload!) {
createUsers(file: $file)
}
''')
with open("YOUR_FILE_PATH", "rb") as f:
params = {"file": f}
result = client.execute(
query, variable_values=params, upload_files=True
)
print(result)
If you activate logging, you can see some message exchanged between the client and the backend.

Angular, error 500 after sending the request in the header

I have a hard time passing the right angular request to the header. This is my service:
import { Injectable } from '#angular/core';
import { HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpHeaders }
from '#angular/common/http';
import { Utente } from '../model/Utente ';
import { Prodotto } from '../model/Prodotto ';
import { OktaAuthService } from '#okta/okta-angular';
import { Observable, from } from 'rxjs';
import { Carrello } from '../model/Carrello ';
import { userInfo } from 'node:os';
import { getLocaleCurrencyCode } from '#angular/common';
const headers = new HttpHeaders().set('Accept', 'application/json');
#Injectable({
providedIn: 'root'
})
export class HttpClientService {
constructor(
private httpClient:HttpClient, private oktaAuth:OktaAuthService ) {}
getCarr(){
return this.httpClient.get<Carrello[]>('http://localhost:8080/prodotti/utente/vedicarrelloo', {headers} );
}
}
This is my spring method:
#Transactional(readOnly = true)
public List<Carrello> getCarrello(#AuthenticationPrincipal OidcUser utente){
Utente u= utenteRepository.findByEmail(utente.getEmail());
return carrelloRepository.findByUtente(u);
}
In console I get this error (error 500):
https://i.stack.imgur.com/BiONS.png
this error corresponds in my console to "java.lang.NullPointerException: null.
But if I access localhost: 8080, I can see the answer correctly, so I assume there is a problem in passing the request header in angular, can anyone tell me where am I wrong, please? I specify that I get this error only in the methods where the OidcUser is present, the rest works perfectly. Thank you!
You need to send an access token with your request. Like this:
import { Component, OnInit } from '#angular/core';
import { OktaAuthService } from '#okta/okta-angular';
import { HttpClient } from '#angular/common/http';
import sampleConfig from '../app.config';
interface Message {
date: string;
text: string;
}
#Component({
selector: 'app-messages',
templateUrl: './messages.component.html',
styleUrls: ['./messages.component.css']
})
export class MessagesComponent implements OnInit {
failed: Boolean;
messages: Array<Message> [];
constructor(public oktaAuth: OktaAuthService, private http: HttpClient) {
this.messages = [];
}
async ngOnInit() {
const accessToken = await this.oktaAuth.getAccessToken();
this.http.get(sampleConfig.resourceServer.messagesUrl, {
headers: {
Authorization: 'Bearer ' + accessToken,
}
}).subscribe((data: any) => {
let index = 1;
const messages = data.messages.map((message) => {
const date = new Date(message.date);
const day = date.toLocaleDateString();
const time = date.toLocaleTimeString();
return {
date: `${day} ${time}`,
text: message.text,
index: index++
};
});
[].push.apply(this.messages, messages);
}, (err) => {
console.error(err);
this.failed = true;
});
}
}
On the Spring side, if you want it to accept a JWT, you'll need to change to use Jwt instead of OidcUser. Example here.
#GetMapping("/")
public String index(#AuthenticationPrincipal Jwt jwt) {
return String.format("Hello, %s!", jwt.getSubject());
}

Angular 9 - how to properly encode + sign in URL parameter

I spent many hours without success. I know it's a common problem, many solutions but for me works only Interceptor that I want to avoid.
My service - here I get email with plus like john.doe+100#gmail.com
#Injectable({
providedIn: 'root',
})
export class UsersHttpService {
httpParams = new HttpParams({encoder: new CustomEncoder()});
removeUsersFromGroup(groupId: string, email: string): Observable<any> {
console.log(email); //john.doe+100#gmail.com
let parsedEmail = encodeURI(email); //one of many attempts
return this.http.delete(`${this.env.URI}/monitoring/api/v1/groups/${groupId}/users/`, {
params: {
groupId,
email: email.replace(' ', '+')
},
});
}
And my CustomEncoder:
export class CustomEncoder implements HttpParameterCodec {
encodeKey(key: string): string {
return encodeURIComponent(key);
}
encodeValue(value: string): string {
// console.log('encodeValue encodeValue');
// console.log(value);
// console.log(encodeURIComponent(value));
return encodeURIComponent(value);
}
decodeKey(key: string): string {
return decodeURIComponent(key);
}
decodeValue(value: string): string {
// console.log('decodeValue decodeValue');
// console.log(value);
// console.log(decodeURIComponent(value));
return decodeURIComponent(value);
}
}
When I send request from Angular then in the Network tab in web browser I see:
DELETE https://myapp/groups/d39a4f50-8ebd-11ea-a9ae-5103b15ad73b/users/?groupId=d39a4f50-8ebd-11ea-a9ae-5103b15ad73b&email=john.doe 100#gmail.com
with a space! What's wrong? Were is the problem? IN the console I get email with + but in Network tab without space instead of + sign.
My params are properly encoded (there is 200 status from backend (spring boot), email with +) ONLY when I use global interceptor (which should be avoided):
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpParams,
HttpRequest,
} from "#angular/common/http";
import {Injectable} from "#angular/core";
import {Observable} from "rxjs";
import {CustomEncoder} from "./customEncoder";
#Injectable()
export class EncodeHttpParamsInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const params = new HttpParams({
encoder: new CustomEncoder(),
fromString: req.params.toString(),
});
return next.handle(req.clone({params}));
}
}
Does anyone have any idea??? I tried to use:
return this.http.delete(${this.env.ORBITAL_URI}/monitoring/api/v1/groups/${groupId}/users/, {
params: {
groupId,
email: encodeURI(email) //or encodeURIComponent(email)
},
});
and then in Network tab I see something like john.doe%2B%40gmail.com but I get 500 error from backend
My solution - without any interceptor:
removeUsersFromGroup(groupId: string, email: string): Observable<any> {
const params = new HttpParams({
encoder: new CustomEncoder(),
fromObject: {
groupId,
email,
},
});
return this.http.delete(`${this.env.URI}/myapp/v1/groups/${groupId}/users/`, {
params: params,
});
}
Now it works as expected:)

How wait until complet http request in angular-7

import { Injectable } from '#angular/core';
import { Router } from '#angular/router';
import { HttpClient } from '#angular/common/http';
import { Post } from 'src/app/sign-in/post';
#Injectable({
providedIn: 'root'
})
export class NewUserService {
constructor(private router:Router,private http: HttpClient) { }
async signIn(email:any,password:any){
const userDate = {
email:email,
password:password
}
console.log("Before request");
await this.http.post<{
Status: string;
StatusDetails: string;
token: string;
}>("http://localhost:5000/user/signin", userDate)
.subscribe(respond => {
console.log("respond");
if (respond.token) {
//sign susess
}else {
//fail
}
});
console.log("After request")
}
}
This is my servise.ts class. In hear I try to make a post request. Before completing the request other code execute. I expect output like
Before request
respond
After request
But the actual output is
Before request
After request
respond
How can I execute code like
Before request
respond
After request

Visual Studio can't find toPromise

i used Visual Studio for a WebApp-Projekt with Angular2 as frontend and asp.core as backend.
Now i want to get a status from my API. The Api works, i used it first with postman.
In my Angular-Component, the component says it does not know about toPromise(). i think the code works, but visual studio blocked to build the app.
import { Injectable } from '#angular/core';
import { ImportState } from './importstate';
import { Headers, Http } from '#angular/http';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class ImportService {
private headers = new Headers({ 'Content-Type': 'application/json', 'user': 'Superadmin', 'password':'Rest!12345' });
private heroesUrl = 'api/import/'; // URL to web api
constructor(private http: Http) { }
getStatus(type : string): Promise<ImportState> {
return this.http.get(this.heroesUrl + 'getStatus/' + type, { headers: this.headers })
.toPromise()
.then(response => response.json() as ImportState)
.then(r => console.log(r))
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
//console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
}
I hope somebody can help me.

Resources