Background: I'm writing a small web-server in Java using Vert.X. All of that works so far. Currently the web-server is basically acting as an app-server with a few GET/POST endpoints that just return or consume JSON.
I now need to add a few simple UIs to this server. In the spirit of RESTfulness I'd like to keep my URLs clean and also to return data appropriately based on the Accept: string in the request. For example, if you request from your browser http://www.example.com/challenge/fdb123-aa12345-cbbad12-12345 it should try to load the challenge with that GUID and display an HTML form appropriately. If you do so from a commandline and indicate you accept JSON it should return JSON.
My problem is really: how do I write my HTML to extract the challenge-id and then make an ajax query back to my server to get the JSON data to fill in the form? I'm not shooting for anything fancy; the form is mostly static: a textbox, a datepicker and maybe a few other fields, that's it. Loading the JSON data from the same URL with an "accept" type of application/json should return parameters that I can use in my JS/HTML to fill in the form - my only question is, how do I make that request back to my server when I load the HTML? How do I know the challenge ID?
What you describe is a "REST way", one endpoint supplying different outputs based on the header, but most of the frameworks don't do it like that. In frameworks like Ruby on Rails, the output is defined by the suffix: .html, .json
But let's assume that's still what we want to do:
If the Accept: header is JSON, return JSON
Otherwise, return HTML
In HTML, extract some URL parameter, and send it to get JSON
Ok, here we go:
final Vertx vertx = Vertx.vertx();
final Router router = Router.router(vertx);
router.route("/challenge/:id").produces("text/html").handler(ctx -> {
ctx.response().sendFile("index.html");
});
router.route("/challenge/:id").produces("application/json").handler(ctx -> {
final String id = ctx.request().getParam("id");
final Map<String, String> res = new HashMap<>();
res.put("challenge", id);
ctx.response().end(Json.encode(res));
});
vertx.createHttpServer().requestHandler(router::accept).listen(8080, r -> System.out.println("Ready"));
And your client may look like this:
<script>
$(function() {
var path = document.location.pathname.split("/")
var id = path[path.length - 1]
$.ajax({
headers: {
// If you don't limit headers, it will send Accept: */*
Accept: "application/json"
},
url: "/challenge/" + id,
success : function(res) {
console.log(res)
}})
})
</script>
Related
I have an app in ReactJs, using Axios and Papaparse.
I have a page where a user drop a csv file in a box, I automatically download the csv, update and make some change in the data, and send a new csv file to a server.
I did all until I arrive to the part where I need to create a new csv, and upload it to the server.
Here is my code currently :
const data = papaparse.unparse(destinationUpdateData, {
header: true,
skipEmptyLines: true
});
// data is a string in csv format
const file = new File([data as BlobPart], "destination.csv", { type: "text/csv" });
// I get a File type.
const paramsDestination = {
project_id: this.props.projectId,
datastore_id: 'DESTINATIONS',
file: file,
id: ["1", "2","3"]
}
// the data I would like to send is build
Axios.post(`new_item_file_attachment`, params, {headers: {"Content-Type": "multipart/form-data"}})
//I send to the server
The thing is, my server is expecting a request with a content Type of multipart/form-data, but I don't get how manually set my parameter to match this type.
The api call currently don't work, because the data is passed like a json, and the server reject it.
Is it possible to achieve it ?
I tried using FormData, but I can't see how to send boolean and array
Not 100% familiar with Axios but it should be something like this:
var params = new FormData();
params.append("project_id", this.props.projectId);
params.append("datastore_id", 'DESTINATIONS');
params.append("file", file);
params.append("id", JSON.stringify(["1", "2","3"])); // Arrays must be stringified
Axios.post(`new_item_file_attachment`, params)
You definitely need to put everything in FormData object. Last time I was doing this, I also had to remove the "Content-Type": "multipart/form-data" from the header. I believe the correct header should get filled in automatically. Try it with and without that stating a header and let me know if either works.
Here is my solution.
const data = new FormData();
data.append("project_id", id);
data.append("file", file);
axios.post(url, data);
Try and comments when some errors occur.
I am implementing a search for a list of people in MVC ASP.Net Core 2.1. Initially, no records are present and the user enters some filters and gets people returned. Currently, the max amount of records is 400,000 and so if they return all records we end up sending 80 MB of data back to the ajax request which we then loop through. This can scale up quite a bit as the final size of the database will be larger then it is currently.
We first get the data with LINQ and then we return an enumerable which we send back as a JSON Result object.
[HttpGet]
public async Task<IActionResult> GetPeopleList(FilterPersonListViewModel model)
{
_logger.LogInformation(
message: GetLogDetail());
//check if model is empty and if so send a empty collection back to initialise the table
if (IsFilterModelValid(model))
{
ICollection<PersonEntityListViewModel> elvm = new List<PersonEntityListViewModel>();
return Json(elvm);
}
bool isCanstat = _userService.IsInRole(User, Constants.Role.Canstat);
var result = await _entityService.GetFilterPersonListViewModelAsync(model, isCanstat);
var data = result.Model;
return Json(data);
}
I then added the middleware to use Gzip compression in my Startup.cs file by adding the line ConfigureServices and Configure as it says to in https://learn.microsoft.com/en-us/aspnet/core/performance/response-compression?view=aspnetcore-2.1. The problem is it doesn't say how to send the response as Gzip. It says "Submit a request to the sample app with the Accept-Encoding: gzip header and observe that the response is compressed." but it doesn't say how I would enable that header in my response.
Do I have to do anything special to compress my data object when I send it back as Json? I found a few different articles relating to compressing it via GzipStream but then I can't send it back as an ActionResult it would seem?
"ajax": {
"url": "/Person/GetPeopleList",
"type": "GET",
//"contentType": "application/json",
"data": function (d) {
setFilterData();
Object.assign(d, filterData);
return d;
},
"dataSrc": ""
},
Ye okay I needed to enabled EnableHttps = true to my middleware setup. Accidentally looked over that when I was reading the page. After adding that it ended up working as intended.
I tried to use Angular $http.post(url, data) method. But I am facing some problems to post correct data to server (WebAPI). I have tried follwing options but none is working.
var data1 = new Object();
data1.UserName = "UserA1";
data1.Password = "password123";
data1.ConfirmPassword = "password123";
var data2 = angular.toJson(data1);
var data3 = JSON.stringify(data1);
var data4 = { UserName: "UserA2", Password: "password123", ConfirmPassword: "password123" };
var data5 = "UserName=UserA3&Password=password123&ConfirmPassword=password123";
$http.post(url, data1)
$http.post(url, data2)
$http.post(url, data3)
$http.post(url, data4)
$http.post(url, data5)
None is working. What kind of data is correct for this method. I tried JQuery.post() with above data and it works. Its super strange for me why this simple angularjs method so hard to use or I am missing something.
Update:
Basically I am working on following example. I want to register user from client side (/api/Account/Register).
http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api
This is because your server-side expects a request with its content x-www-form-urlencoded.
jQuery's $.post() sends the request with a Content-type of application/x-www-form-urlencoded whereas Angular's $http.post() sends the request with a Content-type of application/json (and also encodes the data as JSON (instad of form-data) if a JS Object is passed).
There are methods you can send x-www-form-urlencoded requests using $http (and there are several related answers on SO), but it involves less straight-forward code.
I suggest you change your server side to consume JSON requests.
Depending on what you have on server side, you should transform your request (that's the case for PHP, for example, or you can read from the input stream: php://input).
See this gist: https://gist.github.com/JensRantil/5713606.
If this is not solving your problem, please inspect the requests angular is creating (using the Developer Tools -> Network tab in Chrome for example), and tell us what you see.
I am facing very strange issue here. I have a servlet running on my machine which renders my web page based on some input parameters.
Now, my screen capture with PhantomJS is not working if I try to send my data as a JSON object as a POST request type. For e.g. if I try:
Client side
var data = {"op": "get"};
page.open(address, 'POST', data, function (status) {
if (status !== 'success') {
console.log('[ERROR] :: Unable to fetch the address - ' + address + ", with data - " + data);
phantom.exit();
} else {
page.render(output);
}
console.log('processing...');
});
Server side
Now, on the server side, I am using Apache Velocity View templating so I have a single method which handles both get and post like :
public Template handleRequest(HttpServletRequest request, HttpServletResponse response,
Context context){
System.out.println(request.getParameter("op"));
//Always null
}
However, if I try sending my data from phantomjs as:
var data = "op=get&..."
It works
Also, at many places elsewhere in my code..I am doing Ajax POST requests to the same servlet and it works perfectly for all those request.
Would anybody explain why my servlet is not reading the JSON parameters passed from Phantomjs?
Servlets deal with simple request, so they only know how to parse (natively) HTTP parameters, either GET parameters from the URL, or POST parameters sent as application/x-www-form-urlencoded. Newer versions of the Servlet specification can also read multipart/form-data.
But there's nothing about JSON mentioned either in the Servlet or the HTTP specifications. So you must use a library that knows how to parse JSON and make the resulting object available in the Velocity context.
I am running a web page that generates random data and displays it in a HTML table. From the table I run a loop to gather the basic information (all rows that exist and exclude headers of table). This data gets stored in a JSON object called jData.
I want to send this data back to the server and store in a sqlite table named data. The way I am trying to do this is therough the YUI IO utility.
I am trying to wade the API documentation, but I am having no luck. I have two buttons on the page. One to generate the data and on to store the data. The store code is as follows:
var savedata = function(){
var tabledata = Y.one("#generatedtable")._node;
var jData = [];
var i = 1;
var length = tabledata.rows.length
while (i<length){
var samplerow = {};
var r = tabledata.rows[i];
samplerow.timestamp = r.cells[0].innerHTML;
samplerow.volts = r.cells[1].innerHTML;
samplerow.amps = r.cells[2].innerHTML;
samplerow.kW = r.cells[3].innerHTML;
samplerow.kWh = r.cells[4].innerHTML;
jData.push(samplerow);
i++;
}
Y.io("./savedata", Y.System_Config.postjData(jData));
};
Using the chrome debugger tools I see the array being stored properly into jData. I need some basic help with Y.io and how to make posts. Any basic help is much appreciated. My server is run bu the Django Python web application framework.
You should read the IO User Guide. Making a POST request with JSON data in YUI is as simple as setting the HTTP method to POST, adding the data and setting the Content-Type to application/json. The only caveat is that you need to turn the JSON object into a string first using JSON.stringify().
Y.io('/savedata', {
method: 'POST',
data: Y.JSON.stringify(jData),
headers: {
'Content-Type': 'application/json'
},
on: {
success: function (id, response) {
// do something with the response from the server, for example
Y.one('#some-node').set('text', response.responseText);
}
}
});
You can read more about all the configuration options for IO in the "Configuration Object" section of the User Guide. There is an example there of a POST request with JSON data.