Setting the “Content-Type” header in HTTP.call on

2020-08-04 10:32发布

问题:

I'm trying to use Meteor's (v1.0) HTTP.call method to communicate with a Python-based server which accepts only application/json content type in header but I cannot set the HTTP header properly in Meteor when calling the API URL from a client side.

With a snippet like this, I get a 415 (Unsupported Media Type) error from Python server:

if (Meteor.isClient) {
  Template.testing.events({
    'click button': function(event, tpl) {
      event.preventDefault();

      var method = 'GET';
      var url = 'http://localhost:6543/test';
      var options = {
        headers: {'Content-Type': 'application/json'}
      }

      HTTP.call(method, url, options, function(error, result) {
        if (error) {
          console.log('ERRR');
          console.log(error);
        } else
          console.log('RESULT');
          console.log(result);
      });
    }

  });
}

However, if I call the same URL from a server side in Meteor like this:

if (Meteor.isClient) {
  Template.testing.events({
    'click button': function(event, tpl) {
      event.preventDefault();

      var method = 'GET';
      var url = 'http://localhost:6543/test';
      var options = {
        headers: {'Content-Type': 'application/json'}
      }

      Meteor.call('APICall', method, url, options, function (error, result) {
        if (error) {
          console.log('CLIENT ERRR');
          console.log(error);
        } else {
          console.log('CLIENT RESULT');
          console.log(result);
        }
      });
    }

  });
}

if (Meteor.isServer) {
  Meteor.methods({
    APICall: function (method, url, options) {
      HTTP.call(method, url, options, function(error, result) {
        if (error) {
          console.log('SERVER ERRR');
          console.log(error);
        } else
          console.log('SERVER RESULT');
          console.log(result);
      });
    }
  });
}

I get a proper response from the server.

On Python side I enabled CORS origins for all possible requests (e.g. cors_origins=('*')).

So... Is is possible to set header on client-side or should I always call this service from server-side?

回答1:

I've never had any success on the client-side either, but it is supposed to. Check out the HTTP.call client part of the meteor HTTP package:

https://github.com/meteor/meteor/blob/devel/packages/http/httpcall_client.js

Mostly it uses the browser XHR object on the client-side which can lead to a host of problems, like incompatibilities and stuff. You can even see an issue referenced on one of the code comments (around line 136)

And when you check out the server implementation you can see it uses the request library (from connect), which, in my book, is very reliable and you can generate uniform results across all users (and not dance around browser differences).

My choice and recommendation for you is obviously going to be server-side calls. Not just because it works and it's reliable, it's also 'safer' on your part as you don't have to expose more inner workings of your system to the client/end-user. Who knows? maybe you have sensitive data on your API run on your Python-based server.