POST request and Node.js without Nerve - post

Is there any way to accept POST type requests without using Nerve lib in Node.js?

By default the http.Server class of Node.js accepts any http method.
You can get the method using request.method (api link).
Example:
var sys = require('sys'),
http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.write(request.method);
response.end();
}).listen(8000);
sys.puts('Server running at http://127.0.0.1:8000/');
This will create a simple http server on the port 8000 that will echo the method used in the request.
If you want to get a POST you should just check the request.method for the string "POST".
Update regarding response.end:
Since version 0.1.90, the function to close the response is response.end instead of response.close. Besides the name change, end can also send data and close the response after this data is sent unlike close. (api example)

Related

Cannot POST with ESP8266 (espruino)

I cannot make post request (get works fine) with espruino.
I've already checked the documentation and it seems pretty equal
here is my code:
let json = JSON.stringify({v:"1"});
let options = {
host: 'https://******,
protocol: 'https',
path: '/api/post/*****',
method: 'POST',
headers:{
"Content-Type":"application/json",
"Content-Length":json.length
}
};
let post = require("http").request(options, function(res){
res.on('data', function(data){
console.log('data: ' + data);
});
res.on('close', function(data){
console.log('Connection closed');
});
});
post.end(json);
The espruino console only return the 'connection closed' console.log.
The node.js server console (hosted on heroku and tested with postman) dont return anything.
Obv the esp8266 is connected to the network
What you're doing looks fine (an HTTP Post example is here), however Espruino doesn't support HTTPS on ESP8266 at the moment (there isn't enough memory on the chips for JS and HTTPS).
So Espruino will be ignoring the https in the URL and going via HTTP. It's possible that your server supports HTTP GET requests, but POST requests have to be made via HTTPS which is why it's not working?
If you did need to use HTTPS with Espruino then there's always the official Espruino WiFi boards, or I believe ESP32 supports it fine too.
you're using a package called "http" and then trying to send a request over https. You should also log out 'data' in the res.close so you can get some errors to work with.

BigCommerce oAuth auth token request always returning 401

I can not figure out what I'm doing wrong. I'm developing an App for BigCommerce and can not get the simple oAuth exchange to work correctly.
The initial get request is being made to https://www.my-app.com/oauth/bigcommerce/auth. This is the code in the controller for that request. It's a Laravel 5.6 app:
use Illuminate\Http\Request;
use Bigcommerce\Api\Client as Bigcommerce;
class BigcommerceOAuthController extends Controller
{
public function auth(Request $request)
{
$object = new \stdClass();
$object->client_id = 'my-client-id';
$object->client_secret = 'my-client-secret';
$object->redirect_uri = 'https://my-app.com/oauth/bigcommerce/auth';
$object->code = $request->get('code');
$object->context = $request->get('context');
$object->scope = $request->get('scope');
$authTokenResponse = Bigcommerce::getAuthToken($object);
$storeHash = str_replace('stores/', '', $request->get('context'));
Bigcommerce::configure(array(
'client_id' => 'my-client-id',
'auth_token' => $authTokenResponse->access_token,
'store_hash' => $storeHash
));
echo "<pre>";
print_r($authTokenResponse);
print_r(Bigcommerce::getTime());
echo "</pre>";
}
}
Every time I try to install my draft app from the BigCommerce control panel, I get an error because $authTokenResponse is not an object. When I debug further into the Bigcommerce\Api\Connection class, I can see that the response from the server is empty, and the status is a 401, which means "Unauthorized".
I can't figure out why I am getting this error. As far as I can see, I'm doing everything right. I've tried urlencoding the string retrieved from $request->get('scope'), since that string becomes unencoded by Laravel, but that didn't seem to help.
I am also confused how this is even supposed to work at all. In the BigCommerce docs, they show this example POST request, which uses application/x-www-form-urlencoded Content-Type and passes the request body as a url encoded string:
POST /oauth2/token HTTP/1.1 Host: login.bigcommerce.com Content-Type:
application/x-www-form-urlencoded Content-Length: 186
client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&code=qr6h3thvbvag2ffq&scope=store_v2_orders&grant_type=authorization_code&redirect_uri=https://app.example.com/oauth&context=stores/{STORE_HASH}
However, if you inspect what's going on in the Connection class, you can see that the Content-Type is being set to application/x-www-form-urlencoded as the docs say, but the request body is being passed in as a json string, not a url string. Shouldn't the request be a url encoded string as the docs suggest?
A couple of things here to check:
Do you have a public URL where you can receive the Auth Callback?
If so, did the store owner registered the app successfully? https://developer.bigcommerce.com/api/registration
When you have the client_id and secret_id. You should have all of the details needed to send a POST request to the BC Auth Token Service at https://login.bigcommerce.com/oauth2/token
The content uses URL encode Make sure to URL encode your content. Be careful of of the encoding of & and = signs when those are actually being used as separators.
More details can be found in this post:
Can BigCommerce Private Apps use OAuth

Does NOT support http GET when sending POST

tried looking around the web a bit and am at a loss.
currently setting up a REST api.
locally using postman i send the POST to the end point and all is well.
once its pushed to the test server and i run the POST
Status: 405 Method Not Allowed
{
"message": "The requested resource does not support http method 'GET'."
}
controller looks like and as said, I am able to post locally just not to test server
[HttpPost, Route("")]
[ResponseType(typeof(string))]
public async Task<IHttpActionResult> CreateSomething([FromBody] obj stuff)
c# generated by post man
var client = new RestClient("http://test-api.someurl.com/makestuff/makethisthing/");
var request = new RestRequest(Method.POST);
request.AddHeader("postman-token", "not sure if this is needed but post man put it here");
request.AddHeader("cache-control", "no-cache");
request.AddHeader("authorization", "Bearer [A Very long OAuth token]");
request.AddHeader("content-type", "application/json");
IRestResponse response = client.Execute(request);
it works fine locally running on local iis (not iis express) on my pc and other dev pc. once put to test server then get that error message. i know i am using post as i am using postman with {{server}} env var and just changing from local to test env so the post itself is not chaining at all
there are currently a handful of other end points in separate web applications that are working fine.
any point in the right direction, thank you
Since you're sure you're requesting via POST, but the error unambiguously says you're attempting a GET, the only thing that makes sense is that there's a redirect occurring. A redirect will actually return a 301 or 302 with a Location header. The client then requests that new URL there via GET, even if the original request was a POST. In other words, the flow would be something like: POST -> 302 -> GET -> 405.
Name the action method with a specific route. E.g. /controller/create-something-post/
[HttpPost, Route("create-something-post")]
[ResponseType(typeof(string))]
public async Task<IHttpActionResult> CreateSomething([FromBody] obj stuff)
{
}

Alamofire http request to local webserver

I'm developing an iPhone app and the plan is to send a JSON packet every so often from the app to a local webserver. To do this, I had planned to use Alamofire. My POST method looks like this:
Alamofire.request(Alamofire.Method.POST, "http://XXX.XX.X.XX:3000/update", parameters: dictPoints, encoding: .JSON)
.responseJSON {(request, response, JSON, error) in
println(JSON)
}
The IP address is marked out, but I've made sure that this corresponds to the IPv4 wireless address of my local server. The server is set to listen to port 3000. The server configuration looks like this:
var express = require('express');
var app = express();
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function (callback) {
console.log("MongoDB connection is open.");
});
// Mongoose Schema definition
var Schema = mongoose.Schema;
var LocationSchema = new Schema({
//some schema here
});
// Mongoose Model definition
var LocationsCollection = mongoose.model('locations', LocationSchema);
// URL management
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
app.get('/update', function (req, res) {
console.log("Got something from the phone!");
});
// Start the server
var server = app.listen(3000, function () {
var host = server.address().address
var port = server.address().port
console.log('App listening at %s:%s',host, port)
})
So, this server seems to work ok. I can test it in my browser and type the URL: http://127.0.0.1:3000 and it will feed me the index.html file. If I type in http://127.0.0.1:3000/update... then I get the "Got something from the phone!" message. However, when I run my app (making sure my phone is on the same wireless network as the server) and the Alamofire method gets called... the response I get is nil. I also don't see the "Got something from the phone!" message. Can anyone let me know why that would be happening... or better yet, how to fix it?
A few thoughts:
You are creating a POST request in Alamofire, but you've told Express to handle GET requests for /update. Use app.post(...) if you want to handle it as a POST.
Your Alamofire code is looking for JSON response, but you don't appear to be creating a JSON response. In the short term, you could use responseString rather than responseJSON, but I presume you really want to change your web service to respond with JSON (to make it easier for the app to parse the responses).
Your Alamofire code sending a JSON request (but clearly when you send a request via the web browser, it's not JSON). Are you sure you wanted to send JSON request? (This is not to be confused with the JSON response issue.) Did you want to use the .URL encoding type parameter, rather than .JSON?
Whenever you have a request that works correctly from a web browser, but not from the app, it's useful to watch both using a tool like Charles and you can then compare how they differ and diagnose the source of the different behavior.
If you are running Express server and iOS Simulator on the same machine, try to use http://0.0.0.0:<port>/<url> instead of the actual IP, it helped in my case.
It sounds like the node server is not bound to the address you expect it to be. You should verify that when you type in the actual IP address in your "http://XXX.XX.X.XX:3000/update" in your web browser that it responds. Your question details suggest you've just been using the loopback address.

XMLHttpRequest Post Method - Headers are stopping function

I'm trying to send an XMLHttpRequest object to my Rails server but the headers are causing my function to stop. Here are my observations:
When I comment out the 3 lines of code that set the headers, then xhr.readyState will eventually equal 4 (alert boxes within the anonymous function fire off).
If any one of the 3 header lines are uncommented, then the xhr object never changes state (none of the alert boxes ever fire off).
function saveUserProfile(){
var user_email = $('#userEmail_box').val();
var xhr = new XMLHttpRequest();
xhr.onreadystatechange=function(){
if (xhr.readyState==4 && xhr.status==200)
{
alert("Yes: " + xhr.readyState);
}
alert("No: " + xhr.readyState);
}
var method = 'POST';
var params = 'userEmail=user_email';
var url = 'http://localhost:3000/xhr_requests.json';
var async = true;
//Need to send proper header information with POST request
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('Content-length', params.length);
xhr.setRequestHeader('Connection', 'close');
xhr.open(method, url, async);
xhr.send(params);
}
My three questions are:
What do I need to change in the code above in order to send data through the POST method?
I'm under the impression that the POST method requires some headers to be sent but am not clear about which ones though "xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');" seems to be one that is often mentioned in references. Can somebody help me understand a) why headers need to be sent and b) which ones need to be sent?
I'm using a rails server and am developing locally. Ultimately, this code will be executed on the client side of a mobile device which will go to a hosted rails server for passing and receiving data. Are there limitations with using the POST method with a rails server? Keep in mind that I plan to use JSON when sending information to the client from the server.
Thanks!
UPDATE: The headers should come AFTER the opening the xhr request but BEFORE sending it:
xhr.open(method, url, async);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('Content-length', params.length);
xhr.setRequestHeader('Connection', 'close');
xhr.send(params);
Hope this post saves somebody else 4 hours.
Does your web page with the JavaScript code also live on localhost:3000? If not, this is considered a cross-domain request, and your server will need to return special headers. So you have two options:
1) Host the web page on the same domain as the server, which will make this a same-domain request.
2) Have your server return the appropriate CORS headers. You can learn more about CORS here: http://www.html5rocks.com/en/tutorials/cors/

Resources