Unable to perform POST operation in React with fetch - reactjs

I am attempting to perform POST request using ReactJS and update in a Mongo-database using Spring-boot. During the compilation of the code I did not get any errors, yet when trying to perform a POST operation I do not get an output. When I refresh the page I get an entry in the database with an ID but with no name.
This is the code for the react application:
async handleSubmit(event){
event.preventDefault();
const {item} = this.state;
await fetch(`/person/new`, {
method : 'POST',
headers : {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body : JSON.stringify({item}),
});
this.props.history.push("/change");
}
The code for POST in Spring-boot is :
public Integer Counter(){
List<Person> p = pr.findAll();
c = 1;
while(pr.existsById(c)) {
c++;
}
return c;
}
#PostMapping("/new")
public void insertPerson(#RequestBody Person person){
Integer id = Counter();
String name = person.getName();
pr.save(new Person(id,name));
c++;
}
This is my site looks when the code is executed ↓
How my site looks
Please help me with this.
PS: DELETE operation is working though.

I think it's a matter of how you call this function. I'd suggest invoking it like so: onClick = { async (e) => await { this.handleSubmit(e); } }

Related

sveltekit TypeError: immutable

I'm using sveltekit 1.0.0-next.483 running with npm run dev -- --host
connecting to an endpoint with a mobile device i get this error:
typeError: immutable
at Headers.append ([..]node_modules/undici/lib/fetch/headers.js:227:13)
This error only occurs on mobile device, connecting to the local net ip address.
my endpoint: src/routes/gqlendpoint/+server.ts
const base = 'http://localhost:4000/graphql';
export async function POST( opts: { request: Request} ): Promise<Response> {
const { request } = opts;
const body = await request.json();
const response = await fetch(base, {
//credentials:"include",
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
return response;
}
the only way I found to unlock this situation, is by commenting a line of code inside node_modules/undici/lib/fetch/headers.js
// 3. If headers’s guard is "immutable", then throw a TypeError.
// 4. Otherwise, if headers’s guard is "request" and name is a
// forbidden header name, return.
// Note: undici does not implement forbidden header names
if (this[kGuard] === 'immutable') {
**//throw new TypeError('immutable')**
} else if (this[kGuard] === 'request-no-cors') {
// 5. Otherwise, if headers’s guard is "request-no-cors":
// TODO
}
which is certainly not a good solution.
You have to return new Response body to avoid this issue , see example code below.
return new Response('test example')
in place of return response;

Spring JPA Delete Axios, React JS: CORS Error

I am trying to create a delete function that will delete my data using React, which will make an Axios call to my API which will proceed to remove the data from the DB.
I managed to make a somewhat working copy eventually, but why does my original code hit a CORS error?
Function Call
function deleteProposal(refNum) {
console.log('Delete Proposal Clicked', refNum);
const apiData = {
refNum: refNum,
};
AxiosCall.deleteProposal(JSON.stringify(apiData)).then((result) => {
console.log('deleteProposal Result: ' + result);
console.log('deleteProposal Result.data: ' + result.data);
});
}
Axios Call
const deleteProposal = (data) => {
console.log('delete Proposal');
return axiosHTTP.delete('/deleteProposal', data);
};
Spring API
#CrossOrigin
#ResponseBody
#DeleteMapping(value="deleteProposal", consumes = "application/json")
public HttpStatus deleteProposal(#RequestBody HashMap<Object,Object> selectedProposal) {
System.out.println("deleteProposal: "+selectedProposal);
return HttpStatus.OK;
}
Is it because this isn't the right way to do it in the first place, or is it due to something else?
Please note that I am still relatively new to all the technologies I'm using.

Axios POST request passing an empty object to Spring REST API end doing

I am in the middle of learning react/redux and decided to take an old JQuery UI that makes request to Spring REST API and rewrite it in React. I am using Axios to make the request. In my old Query UI , I do the following when a form is submitted.
var formInputs = $(form).serialize();
$.post("/addAttrItem", formInputs, function(updated){
refresh();
showRecord(updated);
displayControlMsg("Record below was added successfully");
}
This is handled by the following code below in Spring
#ResponseBody
#RequestMapping(value="/someURL", method=RequestMethod.POST)
public AttrItem restfulAdd(AttrItem item) throws Exception
{
item.setLastUpdate(new java.util.Date());
itemService.create(item);
return item;
}
When sending the request through JQuery, AttrItem item param populated with all right values sent in by JQuery
However when I try the following axios
axios.post(someUrl, data).then
(res => {
dispatch(addAttributeSync(res));
}).catch(error =>{
alert('add item failed ' + error);
}
the AttrItem item param while not null itself, is empty with none of the fields set to values from the form. I confirmed that the data object contains right data prior to the post request.
See if mapping the HTTP request body to the method argument item using #RequestBody annotation helps.
#ResponseBody
#RequestMapping(value="/someURL", method=RequestMethod.POST)
public AttrItem restfulAdd(#RequestBody AttrItem item) throws Exception
{
item.setLastUpdate(new java.util.Date());
itemService.create(item);
return item;
}
The following seems to have resolved the issue. In React I added header config
return dispatch => {
var config = {
headers: { 'Content-Type': 'application/json' },
};
axios.post(someUrl, data).then
(res => {
dispatch(addAttributeSync(res));
}).catch(error =>{
alert('add item failed ' + error);
}
And I modified my Spring Controller endpoint to set the consumes and produces attribute as follows.
#ResponseBody
#RequestMapping(value="/attributeItem", method=RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public AttributeItem restfulAdd(#RequestBody AttributeItem attributeItem) throws Exception
{
attributeItem.setLastUpdate(new java.util.Date());
attributeItemService.create(attributeItem);
return attributeItem;
}

Authentication in Angular 2, handling the observables

I just started with a Angular 2 project and am trying to get authentication up and running. Inspired by this tutorial I decided to do the following:
Create a custom RouterOutlet class (extending it) to handle the authentication logic whenever a url is called.
I succeeded in this custom class, but am still not sure how to check if a user is authenticated. My situation is as follows, I need to query a get call to a external API, for my development proces it is as follows:
getAdmin() {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.get('http://localhost:3000/admin/is_admin.json', options)
.map(res => res)
.catch(this.handleError)
}
This API call returns true or false. I was wondering what would be the best option to use this information? Should I for example call the following function each time a URL should be checked?:
isAdmin() {
this.getAdmin().subscribe(
data => this.authenticationResult = data,
error => console.log("Error: ", error),
() => return JSON.parse(this.authenticationResult._data);
}
I can't get this up and running because my observable is undefined when using the function I gave as example.
The "problem" is that your method is asynchronous so you need to be careful the way and when you use it.
If you want to use within the activate method of your custom RouterOutlet, you need to leverage observables and reactive programming.
I don't know exactly the way you want to check admin roles:
activate(instruction: ComponentInstruction) {
return this.userService.getAdmin().flatMap((isAdmin) => {
if (this.userService.isLoggIn()) {
if (this._canActivate(instruction.urlPath, isAdmin) {
return Observable.fromPromise(super.activate(instruction));
} else {
this.router.navigate(['Forbidden']);
return Observable.throw('Forbidden');
}
} else {
this.router.navigate(['Login']);
return Observable.throw('Not authenticated');
}
}).toPromise();
}
_canActivate(url, admin) {
return this.publicRoutes.indexOf(url) !== -1
|| this.userService.isLoggedIn();
}
In order to optimize the request, you could lazily (and only once) call the request to check if the user is admin or not:
isAdmin:boolean;
getAdmin() {
if (this.isAdmin) {
return Observable.of(this.isAdmin);
} else {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.get('http://localhost:3000/admin/is_admin.json', options)
.map(res => res)
.catch(this.handleError);
}
}
Another approach will be also to load this hint when authenticating the user. This way, the implementation of the activate method would be simplier:
activate(instruction: ComponentInstruction) {
if (this.userService.isLoggIn()) {
if (this.userService.isAdmin()) {
return super.activate(instruction);
} else if (this._canActivate(instruction.urlPath, isAdmin) {
return super.activate(instruction);
} else {
this.router.navigate(['Forbidden']);
}
} else {
this.router.navigate(['Login']);
}
}
_canActivate(url, admin) {
return this.publicRoutes.indexOf(url) !== -1
|| this.userService.isLoggedIn();
}
I would consider to call getAdmin() somehow as first Step of your app, store the result in a SessionService object which you move around using Dependency Injection. This way any time you need to check the result of getAdmin you can ask the SessionService instance.
I hope this helps

How to call Web Api method that

I am writing a Web API method to export a PDF file from querying data from database.
I am able to get this worked by calling directly and get the result as expected. But calling this method from angularjs is not working. I see that the method is called but download is not happenning. I saw in someposts that ajax calls dont work on downloading the content....if so what are the other options to call this method and get the file downloaded ? Can somebody give some hint on how to get this worked ?
This is the code I wrote on WEB API and angularjs.
[HttpGet]
[Route("ExportAppsData")]
public HttpResponseMessage ExportAppsData(string ids, bool skip)
{
Int64[] convertedIds = new Int64[] { };
if (ids != null)
convertedIds = ids.Split(',').Select(n => Convert.ToInt64(n)).ToArray();
List<App> apps = new List<App>();
if (skip)
apps = _appRepository.GetAllApps().SkipWhile(a => convertedIds.Contains(a.Id)).ToList();
else
apps = _appRepository.GetAllApps().Where(a => convertedIds.Contains(a.Id)).ToList();
List<AppDto> mappedResult = _mapppingEngine.Map<List<App>, List<AppDto>>(apps);
return Request.CreateResponse(HttpStatusCode.OK, mappedResult,new PdfMediaTypeFormatter());
}
function exportAppsData(appIds, skipFlag) {
return $http(
{
url: ngSettings.apiServiceUri + 'api/Apps/ExportAppsData',
responseType : ArrayBuffer,
params: { ids: appIds.join(","), skip: skipFlag },
contentType: 'application/json; charset=utf-8',
headers: {
Accept: "text/csv; charset=utf-8",
},
method: "GET",
}
);
}
You need to set your Accept header to application/pdf instead of text/csv; charset=utf-8.

Resources