Passing very large XML data as params in Angular 2 to Rails - ruby-on-rails

I have a text area, where user can paste any XML. Then on click of a button, the XML is sent to the server to get the response. I find, this works perfectly with smaller XMLs. But, my issue is, when I send a large XML, the Rails server log simply says
!! Invalid
request
CODE
Provider.ts
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { HttpClientService } from './../services/httpclient.service';
#Injectable()
export class QuestWebServiceTestProvider {
constructor(private http: HttpClientService) {}
getResponseXML(params) {
return this.http.get('/api/v1/get_response_xml?request_xml=' + params["request_xml"]);
}
}
Component.ts (this passes the XML read from textarea to provider)
getResponse() {
let requestXml = this.requestXmlElement.nativeElement.value.trim();
if(requestXml.length > 0) {
let requestXmlJson = encodeURI(requestXml);
this.<provider>.getResponseXML({request_xml: requestXmlJson).subscribe(
data => {
console.log(data);
}
)
}
}
What is the best way to send larger XMLs?

Sorry, for the typo in the question. I actually use POST request.
Thanks Pavel Mikhailyuk for pointing it.
This is how I fixed it:
Instead of framing the query params manually as:
...get_response_xml?request_xml=' + params["request_xml"]
I pass the XML as options to HTTP POST:
let options = {request_xml: params["request_xml"] };
return this.http.post('...get_response_xml?, options);
This seemed to work !!!

Related

SvelteKit: Change UI on incoming Post Request

Assume the following:
src/route/create/+server.ts:
import { json } from "#sveltejs/kit";
import type { RequestHandler } from "./$types";
import { testStore } from "$lib/stores/testStore";
export const POST = (async ({ request }) => {
console.log("POST REQUEST INCOMING");
testStore.set("something") << THIS IS NOT WORKING AS EXPECTED
return json({ message: "hi" });
}) satisfies RequestHandler;
Then, in some svelte component:
testStore.subscribe((value) => {
if (value) {
console.log("Post request came in!");
}
});
When I perform a post request, I can see this part "POST REQUEST INCOMING", but the value of the store is not being updated.
In general, I want to do this: The client makes a request to some other Python backend. That backend does something which takes maybe 10 seconds. Once Python is done, it sends a POST request back to the client (the /create endpoint from above), basically saying that the process is complete. Then the client is supposed to change its UI, notifying the user.
Any idea how I can do this?
I've already tried the code above, which didn't work...

NestJS req.body from POST method is empty/undefined when awaiting ArrayBuffer

I am trying to send file from Client (Angular) to the NestJS same way like it is working now with Java-springboot API.
I am using POST method in NestJS but, unfortunatelly I am not able to got any data from the body :
here is the code :
#Post('/uploadExportFile')
uploadAttachment(#Req() req: Request, #Body() attachment: ArrayBuffer): any {
console.log(attachment);
return {};
}
content-type is set in header on Client side, I am not sure if I need to set content-types there ? Content type depends on file mimetype it should be (application/pdf/png/jpeg)..not multiform or what I need to do to achieve that attachment object will not return empty {} .
req.body is undefined
What I need to do with that file is to again change it back to Base64 (in angular it is in Base64) but Java API consumes only byte[] so I need to keep that like it is on FE.
any suggestions what is wrong in this "simple" code?
** EDIT **
====↓ EDIT ↓====
Solution: request.body is undefined is:
NestJS use as default body jsonBody, so in that case you have to override for specific routes that you want to use raw-body, and if raw-body is used insted of jsonBody, then the body from request is not undefined and it contain ArrayBuffer.
What you need to do is something like this;
Create rawBody middleware raw-body.middleware.ts
import { Injectable, NestMiddleware } from '#nestjs/common';
import { Request, Response } from 'express';
import * as bodyParser from 'body-parser';
#Injectable()
export class RawBodyMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => any) {
bodyParser.raw({type: '*/*'})(req, res, next);
}
}
app.module.ts
export class AppModule implements NestModule {
public configure(consumer: MiddlewareConsumer): void {
consumer
.apply(RawBodyMiddleware)
.forRoutes({
path: '/uploadExportFile',
method: RequestMethod.POST,
})
.apply(JsonBodyMiddleware)
.forRoutes('*');
}
}
and you need to disable bodyparser in main.ts
const app = await NestFactory.create(AppModule, { bodyParser: false })
in new version of NestJS is introduced new option raw-body but I have no possibility to test that https://docs.nestjs.com/faq/raw-body#raw-body
frist thing send the content-type application/x-www-form-urlencoded
and sure you have add UseInterceptors Like FileInterceptor
you can import FileInterceptor
if you need to get buffer try use file.buffer
import {FileInterceptor} from "#nestjs/platform-express";
#Post('upload')
#UseInterceptors(FileInterceptor('file'))
async upload(#Req() request: RequestWithUser, #UploadedFile() file) {
if (!file) {
throw new HttpException('File is required', HttpStatus.BAD_REQUEST);
}
// you have file
return await this.storageService.upload(file, request.user);
}

using headers in HTTP client

I am trying to develop a dashboard in angular 7. I wanted to access an URL and get the JSON response in my dashboard. the problem is that my code works fine with an open source URL. but there are few end points, which have authorization request. Aim is to add the headers like the JWT token, authorization to my service and display the data in my dashboard.
I found few resources on the internet which are confusing.
Below is my code I tried in my service.ts
import { Injectable } from '#angular/core';
import {HttpClient} from "#angular/common/http";
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) { }
getlocations() {
return this.http.get('https://jsonplaceholder.typicode.com/users')
}
}
Any lead on how to add the header and access them would be really helpful.
The simplest way is to modify a specific request by adding HttpHeaders with the authorization parameter. Here's an example:
getlocations() {
return this.http.get(
'https://jsonplaceholder.typicode.com/users',
{ headers: new HttpHeaders({'Authorization': 'Bearer ' + token}) }
);
}

How would I go about getting AJAX data *from* Rails and render it back in Rails?

The project I've been working on has taken many shapes over the last few months, but its most recent incarnation was one which involved a RESTful Rails backend with React, Jade and Express on the frontend. This worked fine since React and Jade handled any data rendering on the frontend, and it allowed us to break out the requests from one monolithic request to about three much, much tinier ones.
The mandate is now to merge the view components into Rails, and this...is where I'm stuck.
As I said before, the world was different - The RESTful Rails routes were on one side of the fence, and the client was on another, meaning that AJAX requests were the only game in town. Here are some sample routes:
v1/property/:field
v1/property2/:field
v1/property3/:field
All of these routes work independently of any UI, so for the purpose of this question, we should treat them as a data source.
These are all requested on a single dashboard-like page, with each request pertaining to a specific part of it, all backed by a search bar which allows one to insert a specific calendar date. I've got this visually working now in a single view (mind the polygons).
My main concern is the request to each of the three other parts of the view. It is unclear to me how to have each of these independently make their requests to the appropriate RESTful route with the appropriate value provided by the search bar.
I've tried a hackish approach to this particular problem:
Within the search module's JS file, on its submission, create a new event called doingSearch.
Use this event to provide the information I received from the search module's <input> tag, falling back to its placeholder value if I don't have anything else.
In _property.js.erb, I listen for this event and emit two AJAX requests:
The first request is to the endpoint, v1/property/:field, and if it is successful, the second request is a POST, which goes to a route /board/:field/handle_post. The belief here is that I have more control over this route, and can dictate what's rendered here.
I then render _property.html.erb at the end of _property.js.erb, but I would rather like to pass the JSON data into _property.html.erb as if it were a Rails model for simplicity's sake. If at all possible, the logical solution would be to render the view after the POST request had been submitted, but that's another sticking point - I'm unclear on how to approach that.
How would I go about accomplishing this?
If you are dealing with data you will want to use the flux pattern. Here is an example from https://github.com/calitek/ReactPatterns React.14/ReFluxSuperAgent. The api.store handles the actions that initiate an ajax request. The util/api.js handles the ajax requests. The basic.store receives the data through actions from util/api.js and passes the data on to the control component with events. The control component could then pass the relevant data on to other components as props. Those components can trigger events that are listened to by the api.store.
import Reflux from 'reflux';
import Actions from './Actions';
import ApiFct from './../utils/api.js';
let ApiStoreObject = {
newData: {
"React version": "0.14",
"Project": "ReFluxSuperAgent",
"currentDateTime": new Date().toLocaleString()
},
listenables: Actions,
apiInit() { ApiFct.setData(this.newData); },
apiInitDone() { ApiFct.getData(); },
apiSetData(data) { ApiFct.setData(data); }
}
const ApiStore = Reflux.createStore(ApiStoreObject);
export default ApiStore;
import request from 'superagent';
import Actions from '../flux/Actions';
let uri = 'http://localhost:3500';
module.exports = {
getData() { request.get(uri + '/routes/getData').end((err, res) => { this.gotData(res.body); }); },
gotData(data) { Actions.gotData1(data); Actions.gotData2(data); Actions.gotData3(data); },
setData(data) { request.post('/routes/setData').send(data).end((err, res) => { Actions.apiInitDone(); }) },
};
import Reflux from 'reflux';
import Actions from './Actions';
import AddonStore from './Addon.Store';
import MixinStoreObject from './Mixin.Store';
function _GotData(data) { this.data1 = data; BasicStore.trigger('data1'); }
let BasicStoreObject = {
init() { this.listenTo(AddonStore, this.onAddonTrigger); },
data1: {},
listenables: Actions,
mixins: [MixinStoreObject],
onGotData1: _GotData,
onAddonTrigger() { BasicStore.trigger('data2'); },
getData1() { return this.data1; },
getData2() { return AddonStore.data2; },
getData3() { return this.data3; }
}
const BasicStore = Reflux.createStore(BasicStoreObject);
export default BasicStore;
import React from 'react';
import BasicStore from './../flux/Basic.Store';
let AppCtrlSty = {
height: '100%',
padding: '0 10px 0 0'
}
const getState = () => {
return {
Data1: BasicStore.getData1(),
Data2: BasicStore.getData2(),
Data3: BasicStore.getData3()
};
};
class AppCtrlRender extends React.Component {
render() {
let data1 = JSON.stringify(this.state.Data1, null, 2);
let data2 = JSON.stringify(this.state.Data2, null, 2);
let data3 = JSON.stringify(this.state.Data3, null, 2);
return (
<div id='AppCtrlSty' style={AppCtrlSty}>
React 1.4 ReFlux with SuperAgent<br/><br/>
Data1: {data1}<br/><br/>
Data2: {data2}<br/><br/>
Data3: {data3}<br/><br/>
</div>
);
}
}
export default class AppCtrl extends AppCtrlRender {
constructor() {
super();
this.state = getState();
}
componentDidMount() { this.unsubscribe = BasicStore.listen(this.storeDidChange.bind(this)); }
componentWillUnmount() { this.unsubscribe(); }
storeDidChange(id) {
switch (id) {
case 'data1': this.setState({Data1: BasicStore.getData1()}); break;
case 'data2': this.setState({Data2: BasicStore.getData2()}); break;
case 'data3': this.setState({Data3: BasicStore.getData3()}); break;
default: this.setState(getState());
}
}
}

In dart httpRequest getstring always error

I established a RESTful server, and I can get a simple string with my Chrome or IE using this URL: "http://localhost:8080/WebService/RESTful/getString"
But when using Dart, it always returns a error message:
"[object XMLHttpRequestProgressEvent]"
From the onError() callback method,
I'm sure that server returns a string with "text/plain" MIME type in Java.
Here is the code:
import 'dart:html';
void main() {
HtmlElement btn = document.body.querySelector("#btn");
btn.onClick.listen(onClick);
}
void onClick(Event v) {
var url = "http://localhost:8080/WebService/RESTful/getString";
HttpRequest.getString(url).then((str) {
window.alert(str.toString());
}, onError: (e) {
window.alert(e);
});
}
Who can help me ?
If you try to fetch resources from another server than the one your page was loaded from, this server needs to return CORS headers otherwise your browser refuses to fetch form this other server.
It depends on your server how this can be configured or added.
See for example
- How do you add CORS headers in Redstone interceptor?
- CORS with Dart, how do I get it to work?

Resources