Meteor Get request - meteor

Bear with me for any mistakes/wrong terminology since I am new to all this. I am using meteor to develop my project and i need to make a get request to an external API. (I already added meteor add http) Below is my code:
HTTP.call( 'GET', 'url', {}, function( error, response ) {
if ( error ) {
console.log( error );
} else {
console.log( response );
}
});
If i use the code inside my Client folder in Meteor I get the following error No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access meteor It has something to do with CORS which I didn't understand how to implement. If I use the code above in my Server side I do get the correct response in the console but how do I use it as a var on my client javascript code?

Tou can use .call function of HTTP and pass your header in options:
HTTP.call(method, url, [options], [asyncCallback])
Arguments
method String
The HTTP method to use, such as "GET", "POST", or "HEAD".
url String
The URL to retrieve.
asyncCallback Function
Optional callback. If passed, the method runs asynchronously, instead of synchronously, and calls asyncCallback. On the client, this callback is required.
Options
content String
String to use as the HTTP request body.
data Object
JSON-able object to stringify and use as the HTTP request body. Overwrites content.
query String
Query string to go in the URL. Overwrites any query string in url.
params Object
Dictionary of request parameters to be encoded and placed in the URL (for GETs) or request body (for POSTs). If content or data is specified, params will always be placed in the URL.
auth String
HTTP basic authentication string of the form "username:password"
headers Object
Dictionary of strings, headers to add to the HTTP request.
timeout Number
Maximum time in milliseconds to wait for the request before failing. There is no timeout by default.
followRedirects Boolean
If true, transparently follow HTTP redirects. Cannot be set to false on the client. Default true.
npmRequestOptions Object
On the server, HTTP.call is implemented by using the npm request module. Any options in this object will be passed directly to the request invocation.
beforeSend Function
On the client, this will be called before the request is sent to allow for more direct manipulation of the underlying XMLHttpRequest object, which will be passed as the first argument. If the callback returns false, the request will be not be send.
Souce: Here

Fixed it. On client side
Meteor.call("getURL",'url',{},function(err,res){
if(err){
console.log('Error: '+err);
}
if(!err){
console.log('Response: '+res);
}
and on server
Meteor.methods({
'getURL': function(url_l){
console.log("Request: "+url_l)
return HTTP.get(url_l)
}
});

Related

"Handler crashed with error runtime error: invalid memory address or nil pointer dereference", but POSTMAN is ok! Why this happens?

I work with vue and go for frontend and backend respectively. I send post request to my server and get 403 error code message(notAllowed). But in postman I get the objects and is fine.
Vue and Vuex
My axios post request:
const response = await this.$axios.post(`http://localhost:8000/v1/org/${params.organization}/kkms/${params.kkm}/closeShift`,{
headers : {
'token' : this.state.token.value
}});
I know I should also use other properties like 'Content-Type' and etc in headers, but know it works well with only "token" property in the other requests. I want to know whether problem in backend or frontend?
It seems you have a mistake in the axios request.
You are receiving a 403, that means you are not authorized (or sometimes something else, check the comments in the question and down here ).
As can be found in axios docs, the post request looks like this:
axios.post(url[, data[, config]]).
It accepts the config (so the headers) as THIRD parameter, while you are setting it as second parameter. Add an empty FormData object as second param, and just shift your config to the third param.
const fakeData = new FormData();
const response = await this.$axios.post(`http://localhost:8000/v1/org/${params.organization}/kkms/${params.kkm}/closeShift`,
fakeData,
{
headers : {
'token' : this.state.token.value
}
});

GET request working on postman but not in browser

I have encountered a strange issue with a GET request that I am stuck on.
I am calling a GET request from my ASP.Net application that works fine in postman but does not hit my userGETReq.onload.
function getUser(username){
userGETReq.open("GET", userURL + "/" + username);
userGETReq.send();
userGETReq.onload = () => {if(userGETReq.status === 200){//cool stuff }}
I am running on a localhost in the browser - the function to start this is being called from a form that returns false.
<form onsubmit="login(this); return false">
POSTMAN
Picture of successful postman response for the GET request
I have other GET requests from the same application that work.
The only difference between this and the other one that works is that it has a 'variable' that gets passed in and has a set route:
[Route("api/User/{username}")]
public List<User> Get(string username)
This is how my CORS is set up
that is the problem
CORS:
EnableCorsAttribute cors = new EnableCorsAttribute("*","*","*");
config.EnableCors(cors);
Any help would be greatly appreciated!
The waring I am getting:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:56390/api/user/test3. (Reason: CORS request did not succeed).
to resolve CORS issue, you can write another method in service as follows
Every time service call is made, OPTIONS is triggered first to check if the service call is allowed and once the OPTIONS returns allowed, actual method is invoked
//here you can add URL of calling host or the client URL under HEADER_AC_ALLOW_ORIGIN
#OPTIONS
#Path("/yourservice/")
#LocalPreflight
public Response options() {
String origin = headers.getRequestHeader("Origin").get(0);
LOG.info(" In options!!!!!!!!: {}", origin);
if ("http://localhost:4200".equals(origin)) {
return Response.ok()
.header(CorsHeaderConstants.HEADER_AC_ALLOW_METHODS, "GET,POST,DELETE,PUT,OPTIONS")
.header(CorsHeaderConstants.HEADER_AC_ALLOW_CREDENTIALS, "false")
.header(CorsHeaderConstants.HEADER_AC_ALLOW_ORIGIN, "http://localhost:4200")
.header(CorsHeaderConstants.HEADER_AC_ALLOW_HEADERS, "content-type")
.build();
} else {
return Response.ok().build();
}
}

Arbitrary response content types in Feathers

I have a custom service that must return data in CSV format.
I can't use a standard Express route, because I need Feathers' hooks on this endpoint.
I couldn't find an example of a Feathers service returning non-HTML, non-JSON data, and have found no way to specify a response content type.
Using res.set('Content-Type', 'text/csv') before returning from the service method didn't work; the final Content-Type header was reset to application/json, even though the method's return value was a regular string.
How can I properly set arbitrary response content types in Feathers' custom service methods?
You can customize the response format like this:
const feathers = require('feathers');
const rest = require('feathers-rest');
const app = feathers();
function restFormatter(req, res) {
res.format({
'text/plain': function() {
res.end(`The Message is: "${res.data.text}"`);
}
});
}
app.configure(rest(restFormatter));
The complete documentation can be found here.
Using your own service specific middleware to send the response should also work.

Check logged user with normal and ajax request

I use interceptor to check if a user is logged in every controller call like this :
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) {
if(request.getSession().getAttribute("user") == null) {
response.sendRedirect("redirect:/login?next="+
URLEncoder.encode(
request.getRequestURL().toString() + "" +
(request.getQueryString() != null ? "?" + request.getQueryString() : "")
,"utf-8");
return false;
}
return true;
}
It work fine for normal request but for ajax request i can't make a response.sendRedirect(..).
How to know if it's a ajax or normal request ?
How can i do it like if i got a ajax error ?
$.ajax({
.....
success : function(data) { ...... },
error : function(){
alert("login error"); // or
document.location = '/path/login' // or something else
}
});
There a other way to handle it rather than using interceptor ?
1. How to know if it's a ajax or normal request ?
You can check inside your interceptor for the existence of the X-Requested-With header. This header is always added to the ajax request by the jQuery library (to my knowing almost all major js libraries add it as well) with the purpose of preventing the Cross-Site request forgery. To figure out if the request is ajax, you can write your preHandle method like
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) {
String requestedWith = request.getHeader("X-Requested-With");
Boolean isAjax = requestedWith != null ? "XMLHttpRequest".equals(requestedWith) : false;
...
}
2. How can i do it like if i got a ajax error ?
As you've already noticed, ajax request don't recognize server side redirects, as the intention of the server side redirects is to be transparent to the client. In the case of an ajax request, don't do redirect rather set some status code to the response e.g. response.setStatus(respCode) or add a custom header e.g. response.setHeader("Location", "/path/login"), and read it through in the jQuery's complete method which is a callback that follows after either success or error, e.g.
$.ajax({
//...
complete: function(xhr, textStatus) {
console.log(xhr.status);
console.log(xhr.getResponseHeader('Location'));
// do something e.g. redirect
}
});
3. There a other way to handle it rather than using interceptor ?
Definitely. Checkout Spring Security. Its a framework, and adds a bit to the learning curve, but its well worth it. It will add much more than a custom solution, e.g. you'll get authorization mechanism on top of the authentication. When your application matures, you'll notice that the straigthforward implementation that you're on to now, has quite a few security flaws that are not hard to exploit e.g. session fixation, where spring security can easily protect you. There's plenty of examples online, and you'll get better support here on the SO in comparison to any custom solution. You can unit test it, an asset I personally value very much
You could simply:
Refuse ajax requests before the user is properly logged in
once the user logs in, set a security token in the session or somewhere
pass that token in the ajax request and use that token to validate on the server side prehandle
in your case you would check the existence of the token before running into the code
Also, the preHandle does not have to apply to every routes, you could also have different routes each with different authorisation, prehandle, code.

Meteor http calls limitations

Currently, I use the built-in meteor http method (see http://docs.meteor.com/#http) for issuing http calls, on both my client and my server.
However, I'm experiencing two issues:
is it possible to cancel a request?
is it possible to have multiple query parameters which share the same key?
Are these just Meteor limitations, or are there ways to get both to work using Meteor?
I know I could you jquery on the clientside, and there must be a server-side solution which supports both as wel, but I'd prefer sticking with meteor code here.
"is it possible to cancel a request?"
HTTP.call() does not appear to return an object on which we could call something like a stop() method. Perhaps a solution would be to prevent execution of your callback based on a Session variable?
HTTP.call("GET", url, function(error, result) {
if (!Session.get("stopHTTP")) {
// Callback code here
}
});
Then when you reach a point where you want to cancel the request, do this:
Session.set("stopHTTP", true);
On the server, instead of Session perhaps you could use an environment variable?
Note that the HTTP.call() options object does accept a timeout key, so if you're just worried about the request never timing out, you can set this to whatever millisecond integer you want.
"is it possible to have multiple query parameters which share the same key?"
Yes, this appears to be possible. Here's a simple test I used:
Meteor code:
HTTP.call("GET", "http://localhost:1337", {
query: "id=foo&id=bar"
}, function(error, result) {
// ...
});
Separate Node.js server: (just the basic example on the Node.js homepage, with a console.log line to output the request URL with query string)
var http = require('http');
http.createServer(function(req, res) {
console.log(req.url); // Here I log the request URL, with the query string
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
When the Meteor server is run, the Node.js server logged:
/?id=foo&id=bar
Of course, this is only for GET URL query parameters. If you need to do this for POST params, perhaps you could store the separate values as a serialized array string with EJSON.stringify?

Resources