How to read POST data with node.js without using express or connect - forms

Edit
Make sure you don't juxtapose the request and response objects. things will be easier if you dont.
I am trying to POST data from a form with two inputs to a specific url node responds to.
Originally I was using the javascript xmlHTTPrequest object to send it. The data was received but node could never read the object I tried sending which was JSON format. Here is what it looked like when I converted it to a string:
{ output: [],
outputEncodings: [],
writable: true,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
useChunkedEncodingByDefault: true,
_hasBody: true,
_trailer: '',
finished: false,
socket:
{ _handle:
{ writeQueueSize: 0,
socket: [Circular],
onread: [Function: onread] },
_pendingWriteReqs: 0,
_flags: 0,
_connectQueueSize: 0,
destroyed: false,
errorEmitted: false,
bytesRead: 8442,
bytesWritten: 1669569,
allowHalfOpen: true,
writable: true,
readable: true,
This was not the full string. I switched over to use an ajax post request instead because I thought serializearray() might create a different format that node could read but it was the same. My server side code is essentially just:
function email(request, response)
form = '';
request.setEncoding("utf8");
request.on('data', function(chunk) {
console.log('data received');
form += chunk.toString();
});
request.on('end', function() {
console.log('done receiving post data');
});
My form looks like this
<form name="email" action="javascript:true;">
<input type="text" name="address" value="Enter your email address" onFocus="this.value=''">
<input class="special" type="text" name="honeypot">
<input type="submit" value="submit">
</form>
If I try parsing with JSON.parse, there is an error caused by unexpected o
If I try parsing with querystring, it returns an empty object
If I try something like console.log(form.address) the output is undefined but should be one of the values i submitted in the form.
my http server would route to /email and this is the function that responds to /email.
I checked and I know the on 'data' event has not expired because my code is set up to notify me of a 'data'event and I can see the event happening. Locally, this code works fine and I can read the data submitted but on the development server it just doesn't work.
I know people will say I should be using connect or express but let's just suppose that was not an option, how could I get node to correctly process this data? The jquery that submits the form is more or less standard. Many thanks!
EDIT:
Sorry, I thought the problem would be fixed as I noticed immediately the posted string was not JSON. Here is the code I am using to send the post.
$(document).ready(function() {
$("#email").submit(function(event) {
event.preventDefault();
var data = $(this).serializeArray();
$.ajax({
type: 'POST',
dataType: 'json',
url: '/email',
data: JSON.stringify(data),
success: function(msg) {
$("#aviso").html(msg);
}
});
});
});
Here is the string the data variable holds:
[
{
"name": "address",
"value": "foo#bar.com"
},
{
"name": "honeypot",
"value": "irobot"
}
]
This is valid JSON as per jsonlint. But still the same error when it reaches the server. Node handles the 'data' event and all is well until I try to parse the string, it causes an error undefined:1 unexpected o.

The data you're sending is not valid JSON, which requires that all object keys are double-quoted.

Related

REST Call in MDriven, construct of HEADER?

I am trying to model the following REST call in MDriven
jQuery.ajax({
type: 'POST',
url: 'http://server.net/api/server/search.php',
data: {
'apikey': xxxxxx,
'apiversion': '3',
'action': "search",
'type':'near',
'lat':'59.91673',
'long': '10.74782',
'distance': '2000',
'limit': '10'
},
success: printJsonResponse,
dataType: 'json'
});
The ViewModel would as I understand it be as follows:
But it is hard to test if this is the "same" (and it doesn't work)
One way to see what is actually sent is to send your data to some echo service that just returns what it gets.
I think there must be REST services for this. I googled "Rest echo service" and got this for example:
https://postman-echo.com/get?foo1=bar1&foo2=bar2
Try to send your request to https://postman-echo.com and then write out the result.

Retrieving params with sinatra on form submit. Params is undefined

I am having trouble accessing params in Sinatra after submitting a form. This is my form:
function submitForm(e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '/mix_addresses',
//grab the inputs from address_section
//data: $('.add_address_section .add_address_field').map(function() { return $(this).val() }),
data: [1,2,3],
dataType: "json",
success: function(data) {
debugger;
}
});
}
And this is my endpoint:
require 'sinatra'
require 'jobcoin_client'
get '/' do
erb :add_coins
end
post '/mix_addresses' do
puts params
end
I'm getting to the endpoint, but the params are blank. Shouldn't it be [1,2,3]? Instead, it's:
{"undefined"=>""}
Anyone see what I'm doing wrong?
Several issues here :)
Sinatra configuration
Main problem is coming from the fact that Sinatra doesn't deal with JSON payloads by default. If you want to send a JSON payload, then the easiest solution will be :
To add rack-contrib to your Gemfile,
Then, require it in your sinatra app: require rack/contrib
And load the middleware that deals with this issue: use Rack::PostBodyContentTypeParser
And you should be good to go!
Source: several SO post reference this issue, here, here or here for instance.
jQuery ajax call
Also, note that there might be some issues with your request :
You'll need to use a key: value format for your JSON payload: { values: [1,2,3] }
You'll need to stringify your JSON payload before sending it: data: JSON.stringify( ... )
You'll need to set the request content type to application/json (dataType is related to the data returned by the server, and doesn't say anything about your request format, see jQuery ajax documentation for more details).
Eventually, you should end up with something like this on the client side:
function submitForm(e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '/mix_addresses',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({ values: [1,2,3] }),
success: function(data) {
debugger;
}
});
}

Vue-resource can't get response body when HTTP error 500

I'm trying to handle an HTTP 500 error using vue-resource (1.2.1) this way:
const resource = Vue.resource('items');
resource.get().then(
(response) => {
// Do something with response.body
},
(error) => {
// Do something with error.body,
// even if the HTTP status code is 500.
// But for now it's null...
}
);
There is nothing in error.body, while the actual server's response have something to say... And I really want to get this data to be displayed in a cool way for my app's users to be aware of what's going on (rather than opening dev tools and inspect network's response data).
Is there something I'm missing in Vue http config? Or maybe server-side, does my API needs to respond in a specific way? Or even respond special headers? Or, is it simply a limitation (or a bug) of vue-resource?
EDIT
Here is the content of error, picked from a console.log:
Response {
body: "",
bodyText: "",
headers: Headers…,
ok: false,
status: 0,
statusText: "",
url: "http://my.domain/items",
data: ""
}
And, the content of the actual server response (which I expected to be into error.body, but is not), picked from "network" tab in dev tools :
{
"success": false,
"error": {
"message":"this is the error message",
"details":[],
"stackTrace":[]
}
}

Twitter Typeahead.js with Yahoo Finance in AJAX

I am trying to couple the new version of Typeahead.js and using it with JSON that needs to be pulled from AJAX and not from a JSON file like they have in their examples. I just can't get it to work, I don't want to cache the JSON result or anything, I want to pull it live from Yahoo.
My HTML input is <input type="text" id="symbol" name="symbol" autofocus autocomplete="off" placeholder="Symbol" onkeyup="onSymbolChange(this.value)" />
My AJAX/PHP file has this to retrieve data (this part work, I tested it with Firebug)
header('Content-type:text/html; charset=UTF-8;');
$action = (isset($_GET['action'])) ? $_GET['action'] : null;
$symbol = (isset($_GET['symbol'])) ? $_GET['symbol'] : null;
switch($action) {
case 'autocjson':
getYahooSymbolAutoComplete($symbol);
break;
}
function getYahooSymbolAutoCompleteJson($symbolChar) {
$data = #file_get_contents("http://d.yimg.com/aq/autoc?callback=YAHOO.util.ScriptNodeDataSource.callbacks&query=$symbolChar");
// parse yahoo data into a list of symbols
$result = [];
$json = json_decode(substr($data, strlen('YAHOO.util.ScriptNodeDataSource.callbacks('), -1));
foreach ($json->ResultSet->Result as $stock) {
$result[] = '('.$stock->symbol.') '.$stock->name;
}
echo json_encode(['symbols' => $result]);
}
The JS file (this is where I'm struggling)
function onSymbolChange(symbolChar) {
$.ajax({
url: 'yahoo_autocomplete_ajax.php',
type: 'GET',
dataType: 'json',
data: {
action: 'autocjson',
symbol: symbolChar
},
success: function(response) {
$('#symbol').typeahead({
name: 'symbol',
remote: response.symbols
});
}
});
}
I don't think that I'm suppose to attach a typeahead inside an AJAX success response, but I don't see much examples with AJAX (except for a previous version of typeahead)... I see the JSON response with Firebug after typing a character but the input doesn't react so good. Any guidance would really be appreciated, I'm working on a proof of concept at this point... It's also worth to know that I'm using AJAX because I am in HTTPS and using a direct http to Yahoo API is giving all kind of problems with Chrome and new Firefox for insecure page.
UPDATE
To make it to work, thanks to Hieu Nguyen, I had to modify the AJAX JSON response from this echo json_encode(['symbols' => $result]); to instead this echo json_encode($result); and modify the JS file to use the code as suggested here:
$('#symbol').typeahead({
name: 'symbol',
remote: 'yahoo_autocomplete_ajax.php?action=autocjson&symbol=%QUERY'
});
I have to do it in reverse, i.e: hook the ajax call inside typeahead remote handler. You can try:
$('#symbol').typeahead({
name: 'symbol',
remote: '/yahoo_autocomplete_ajax.php?action=autocjson&symbol=%QUERY'
});
You don't have to create onSymbolChange() function since typeahead will take care of that already.
You can also filter and debug the response from backend by using:
$('#symbol').typeahead({
name: 'symbol',
remote: {
url: '/yahoo_autocomplete_ajax.php?action=autocjson&symbol=%QUERY',
filter: function(resp) {
var dataset = [];
console.log(resp); // debug the response here
// do some filtering if needed with the response
return dataset;
}
}
});
Hope it helps!

Bad request when trying to post to wcf rest 4 service

I am playing with the wcf 4.0 rest template and trying to get it to work with jquery.
I have created a new rest template project and added a webform into the same project just to get things simple.
I have slightly modfied the Create Method to look like this
[WebInvoke(UriTemplate = "", Method = "POST")]
public string Create(SampleItem instance)
{
// TODO: Add the new instance of SampleItem to the collection
return (instance.Id == 1) ? "1 was returned" : "something else was returned";
}
Then from my webform I am using this.
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
type: 'POST',
url: "/service1/",
data: { "Id": 1,"StringValue": "String content"
},
success: function (data) {
$('.result').html(data);
},
error: function (error) {
$('.result').html(error)
},
dataType: "json",
contentType: "application/json; charset=utf-8"
});
});
</script>
<div class="result"></div>
However fiddler is returning a 400 error telling me there is a request error. Have I done something wrong?
400 can also mean something in your service went wrong. Did you try to attach a debugger to the Rest-service?
Tried to create a .Net-console application (create the request using HttpClient) and communicate with your service?
I ran into same error, after half hour of testing I saw just some error occured in the REST-service.