Grails AsyncHttpBuilder configuration - json

I'm creating a service in Grails 3 to post a json request to a slack webhook an tried with
compile 'org.grails.plugins:async-http-builder:1.0.0-SNAPSHOT'
however with this code
import grails.gorm.transactions.Transactional
import grails.http.client.*
import grails.async.*
#Transactional
class NotificacionService {
def enviarSlack() {
AsyncHttpBuilder client = new AsyncHttpBuilder()
Promise<HttpClientResponse> p = client.post("https://localhost:8080/foo/bar") {
contentType 'application/json'
json {
title "Ping"
}
}
p.onComplete { HttpClientResponse resp ->
log.debug resp.json
}
}
}
I get a Cannot resolve symbol 'AsyncHttpBuilder'
Any hints or other ways to accomplish the same?

Related

Kotlin Ktor trying to install JsonFeature on the client side but is not recognized

I'm using Ktor client and I'm trying to implement post requests using the serialization provided by the framework.
For some odd reason adding serialization works on the server side but not the client side.
Gradle
plugins {
application
kotlin("jvm") version "1.6.10"
id("org.jetbrains.kotlin.plugin.serialization") version "1.6.10"
}
repositories {
mavenCentral()
maven { url = uri("https://maven.pkg.jetbrains.space/public/p/ktor/eap") }
}
dependencies {
// Ktor server
implementation("io.ktor:ktor-server-core-jvm:$ktor_version")
implementation("io.ktor:ktor-server-content-negotiation-jvm:$ktor_version")
implementation("io.ktor:ktor-serialization-kotlinx-json-jvm:$ktor_version")
implementation("io.ktor:ktor-server-netty-jvm:$ktor_version")
// Ktor client
implementation("io.ktor:ktor-client-core:$ktor_version")
implementation("io.ktor:ktor-client-cio:$ktor_version")
implementation("io.ktor:ktor-client-json:$ktor_version")
implementation("io.ktor:ktor-client-serialization:$ktor_version")
// Arrow
implementation("io.arrow-kt:arrow-core:1.0.1")
// Tests
implementation("ch.qos.logback:logback-classic:$logback_version")
testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
}
In my client side
import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.util.*
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.*
#Serializable
data class TastyCredentials(val login: String, val password: String)
#OptIn(InternalAPI::class)
class TastyWorksBroker() : Broker {
companion object {
val client = HttpClient(CIO) {
install(JsonFeature) // JsonFeature is not recognized by IntelliJ
defaultRequest {
url(baseUrl)
contentType(ContentType.Application.Json)
}
}
}
override suspend fun connect(): Boolean {
val response: HttpResponse = client.post("/sessions") {
body = TastyCredentials(login, password)
}
//
}
install(JsonFeature) does not work, I also tried this:
install(ContentNegotiation) {
json()
}
Does not work either...
Any help?
I actually needed to add another dependency for the client side content negotiation
implementation("io.ktor:ktor-client-content-negotiation:$ktor_version")
Solved

NestJS - accepting multiple MIME types in request body

I am trying to create an endpoint in a HTTP API that receives data periodically from remote devices.
There is a technological shift happening in this project where devices have previously reported data in XML whereas future implementations will shift towards JSON.
I am writing this API in NestJS (7.x) and TypeScript. Data will be coming in through the same endpoint (POST /) and data format is differentiated by the Content-Type header.
#Controller()
export class IngressController {
constructor(private readonly ingressService: IngressService) {
}
/* ... */
#Post('')
#Header('Cache-Control', 'none')
#HttpCode(HttpStatus.NO_CONTENT)
public async receive(
#Headers('Content-Type') contentType: string,
#Req() req: any,
#Body() body: string,
): Promise<InsertResponse> {
if (IngressController.isJson(contentType)) {
return { inserted: await this.ingressService.insertJsonString(req.body) };
}
if (IngressController.isXml(contentType)) {
return { inserted: await this.ingressService.insertXmlString(req.body) };
}
throw new BadRequestException(contentType, 'Unsupported Content-Type');
}
/* ... */
}
Future devices will report data in JSON (indicated by the Content-Type: application/json header in the HTTP request), legacy devices report in XML (Content-Type: application/xml).
It works splendidly for JSON. However, my problem is that req.body (or body respectively) is an empty object in the XML case. I presume the NestJS middleware is doing something and getting confused by XML, but I have found no hints as to allow XML payloads side-by-side with JSON. I don't mind parsing it manually.
As you suspected NestJS has a built-in bodyparser that will not be able to parse xml. What you could do is to plug in a custom middleware where you decide whether to parse the request body as xml or pass the request on the the next handler.
Something like this should work (I'm using express-xml-bodyparser in this example):
import {NestFactory} from '#nestjs/core';
import {AppModule} from './app.module';
import {Request} from "express";
const xmlParser = require('express-xml-bodyparser');
const xmlParserMidleware = xmlParser();
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use((req: Request, res: any, next: any) => {
if (req.path.includes("/api/json-or-xml-handler") && req.header('Content-Type')?.includes('xml')) {
return xmlParserMidleware(req, res, next);
}
next();
});
await app.listen(8020);
}
bootstrap();
Then, in your controller body will either be the parsed json-object or an object representation of your xml:
#Controller()
export class TestControllerController {
#Post('/api/json-or-xml-handler')
receive(#Body() body: any) {
console.log(body);
// ...
}
}

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.

fetch json array from webservice

I am trying to fetch a json array from webservice.
The docs say:
_getIPAddress() {
final url = 'https://httpbin.org/ip';
HttpRequest.request(url).then((value) {
print(json.decode(value.responseText)['origin']);
}).catchError((error) => print(error));
}
If I use this code I get the error:
The method request is not defined for the class 'HttpRequest'
While If I try to import:
import 'dart:html';
I get this error:
Target of URI doesn't exist 'dart:html'
For http requests i recommend the http package.
Then after importing the http package you can use it like that for example:
import 'package:http/http.dart' as http;
_getIPAddress() async {
final url = 'https://httpbin.org/ip';
try {
http.Response res = await http.get(url);
print(json.decode(res.body));
} catch(e) {
print(e);
}
}

Aurelia fetch client: 404 for POST with JSON body

I'm trying to post request with JSON body using aurelia fetch client. Here is my code:
import {inject, NewInstance} from 'aurelia-framework';
import {HttpClient, json} from 'aurelia-fetch-client';
#inject(NewInstance.of(HttpClient))
export class TestClass {
constructor(httpClient) {
this.__httpClient = httpClient.configure(x => {
x.useStandardConfiguration()
.withBaseUrl('http://test.com/api/')
});
}
sendRequest() {
let test= {
paramone: 'One',
paramtwo: 'Two'
};
this.__httpClient.fetch('postdata', {
method: 'post',
body: json(test)
});
}
}
However I get the following error in browser console:
Fetch API cannot load http://test.com/api/postdata. Response for preflight has invalid HTTP status code 404
The problem is that if I don't send json body (i.e. body: '') the request reaches the server! So, there's some issue with the body. Could you please help me to find out the root cause?