CouchdB Jquery Ajax POST CORS - javascript

I am prototyping a very simple webapp. I installed Couch 1.3.1 today and created a database. I am attempting to save a document to my local couch (localhost:5984) with a POST from a client browser also on localhost, but different port (6789)
var dbIp = "http://localhost:5984/commute";
var data = {state:0,timestamp:"faketime"};
$.ajax({
type: 'POST',
crossDomain: true,
contentType: "application/json",
url: dbIp,
data: data,
success: function(result) {
console.log(result);
}
});
I get:
XMLHttpRequest cannot load http://localhost:5984/commute-tracker. Origin http://localhost:6789 is not allowed by Access-Control-Allow-Origin.
I have modified the local.ini to enable CORS as outlined in the couchdb spec with
[httpd]
enable_cors = true
[cors]
origins = *
[cors]
methods = GET, POST, PUT, DELETE
I can see all of these changes reflected in the config file in futon. I have also tested the database with a curl:
curl -X POST localhost:5984/commute -H "Content-Type: application/json" -d '{"tags":"sure","name":"made it"}'
The curl works just fine, but I can't make a similar POST in the browser because of Access Control Allow Origin. What else am I missing, or what can I change to make this POST possible?

Going about this trying to do cross-domain, whether it's CORS or JSONP is not ideal.
Since you actually do control both the web server instance and the couchdb instance (I'm assuming you have admin rights to the server) I'd recommend using a reverse proxy to serve couchdb as an endpoint for the main web app.
If you're using Apache mod_proxy will allow you to do this, or nginx is another great HTTP reverse proxy server...inserting a config directive like:
ProxyPass /couch_db/ http://www.localhost:5984/ (for mod_proxy)
would let you post to http://localhost:6789/couch_db/commute

Related

Are there any alternatives to overriding the 'host' header programatically

I have two services I'm running locally on docker images. One of them is an nginx server with configuration to proxy requests to various other services, and the other is a simple React GraphiQL UI.
The nginx server is not explicitly set up to run on localhost, but when making requests with curl/postman I can explicitly set the host header to be that of the actual url (rather than localhost) and it will then find the correct config and the request will succeed.
The issue is that I would like to call the server from a local instance of my UI, but it's failing because I can't overwrite the host header. I've tried to manually add it to my react fetch request but when I check the request in the browser the header isn't there. After some searching I then found some slack posts saying it's not possible, although no references to why.
return fetch(
edgeUrl(environment) + "/some/endpoint",
{
method: "POST",
headers: {
'Authorization': 'Bearer ' + getApiKey(partner, environment),
'host': 'actual.host.com',
'origin': 'http://localhost/'
},
body: JSON.stringify({ query })
}
)
Is there any other way to override the host used in requests? Possibly another http library I could use? I'd prefer not to have to configure the nginx server for localhost as it is owned by another team.
You should not try change the host header. The browser won't allow you to, and it's not the right way to do it.
As I see it, you have 2 options:
Configure NGINX to accept requests to localhost, if that is its' actually hostname.
Change the hosts file, to include your domain to point to 127.0.0.1, which is equivalent to adding it to DNS.
The Windows Hosts file is located here: C:\Windows\System32\drivers\etc\hosts.
You should add the following to your hosts file after the comments #.
actual.host.com 127.0.0.1
For anyone interested here's some information on possible attacks using the host header and why it's useful to validate it, which is what this service is doing.
https://portswigger.net/web-security/host-header
https://infosecwriteups.com/identifying-escalating-http-host-header-injection-attacks-7586d0ff2c67
I'm going to ask the other team if I can add localhost configuration to their nginx config so that I can make requests locally, looks like my coworker was misinformed in suggesting I override the host header.

AJAX,PHP call HTTPS SSL CERTIFICATE TO REST SERVER

I have constructed a node.js REST server https://server.mydomain.com. And i am using html/javascript/php for the front end, when i implement SSL certificate on the front-end i run into the following problem:
Mixed Content: The page at 'https://front-end.url' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://sistema.url/'. This request has been blocked; the content must be served over HTTPS.
I need to make REST requests to the server over https: right now i am using this with http: but i can not find ajax ssl cross domain requests, is this possible? or how can i do this?
this is one example of my requests
$.ajax({
type: "PUT",
url: url,
headers: {
'token': token
},
contentType: "application/json",
data: JSON.stringify({
name: name,
}),
}).done(function(data) {
console.log(data);
}).fail(function(data) {
console.log(data);
});
});
This restriction was purposely implemented to prevent inadvertent use of non-secure content in what is to be a secure conversation. The resource must implement "https" so that it can be retrieved using a secure connection.
Now that we have "LetsEncrypt.com" to hand out secure (albeit short-lived) HTTPS certificates at zero cost, there really is no excuse anymore not to use HTTPS in your websites. (Automated software is readily available to periodically renew your certificates.)

Making Get request to Yammer API works using Postman tool but not with Vue-Resource

I am trying to integrate Yammer API in my Vue.JS project, for Http calls I am using Vue-Resource plugin. While making GET Http call to get posts from Yammer it gives me following error -
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
I tried postman tool and that gives successful response, but when I try to run the same thing in my Vue.JS project using Vue-Resource plugin it wont work.
The Vue.JS code snippet -
function(){
this.$http.get("https://www.yammer.com/api/v1/messages/my_feed.json").then((data)=>{
console.log(data);
});
In main.vue file i have -
Vue.http.interceptors.push((request, next) => {
request.headers.set('Authorization', 'Bearer my_yammer_token')
request.headers.set('Accept', '*/*')
next()
})
Then I tried the code snippets provided by Postman tool for jquery, that too not working.
jQuery code -
var settings = {
"url": "https://www.yammer.com/api/v1/messages/my_feed.json",
"method": "GET",
"timeout": 0,
"headers": {
"Authorization": "Bearer my_yammer_token",
"Cookie": "yamtrak_id=some_token; _session=some_token"
},
};
$.ajax(settings).done(function (response) {
console.log(response);
});
Though, I found similar questions but nothing worked for me.
I am working this to resolve from last 2 days but getting failed again and again. Please guide/help me.
A browser has higher security requirements than a request in PostMan. In a browser, you are only allowed to make XHR requests to your own current host (combination of domain + port) but not to other remote hosts. To nevertheless make a request to a remote host, you can use the browser built-in CORS. By using this, your browser makes a pre-flight request to the remote host to ask if the current page is allowed to request from that host. This is done via the Access-Control response headers. In your case, this header is probably missing or not allowing your page to access, which is why the request does not go through. Please read further into that topic.
However, in your case, using CORS probably won't be a solution for two reasons: To use CORS, the remote host must present a header which allows every requesting host (*) or your specific one. If you cannot set that setting anywhere on the remote host, it won't work. Second, it is not safe to place your authorization token into client-side JavaScript code. Everybody can just read your JS code and extract the authorization token. For that reason, you usually make the actual API call from the server-side and then pass the data to the client. You can use your own authentication/authorization against your server and then use the static authorization key on the server to request the data from the remote host. In that case, you'll never expose the authorization key to your user. Also, on the server-side, you do not have to deal with CORS as it works just like PostMan or curl as opposed to a browser.

Enable CORS in JIRA REST API

I´m calling JIRA REST API from JavaScript in a Confluence User Macro and I´m facing CORS issues because JIRA and Confluence are on two different domains and preflight request from browser is failing. I have tried several CORS solutions as described below, without any success. So Im begging for some input from others that probably have solved this issue.
JavaScript snippet that is failing:
AJS.$.ajax({
type: "GET",
url: "http://jira.mydomain.com/rest/api/latest/search/?jql=issue%20in%20linkedIssues(SR-45)",
dataType: "json",
contentType: "application/json",
async: false
})
Error message (from Firefox):
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://jira.mydomain.com/rest/api/latest/search/?jql=issue%20in%20linkedIssues(SR-45). This can be fixed by moving the resource to the same domain or enabling CORS.
JIRA Configuration
JIRA Version: 6.4.12
Url: http://jira.mydomain.com
Running Apache in front (proxy): Yes
Response Headers Configuration:
Access-Control-Allow-Headers:origin, content-type, accept
Access-Control-Allow-Methods:POST, GET, OPTIONS
Access-Control-Allow-Origin:*
Confluence added to the whitelist: Yes
Expression: Confluence (http://confluence.mydomain.com)
Type: Application Link
Allow Incoming: True
Confluence Configuration
Confluence Version: 5.8.8
Url: http://confluence.mydomain.com
Running Apache in front (proxy): Yes
Response Headers Configuration:
Access-Control-Allow-Origin:*
JIRA added to the whitelist: Yes
Expression: Confluence (http://jira.mydomain.com)
Type: Application Link
Allow Incoming: True
Tested with browsers:
Chrome (latest)
Safari (latest)
Firefox (latest)
Testing preflight request (OPTIONS) with CURL:
ismar.slomic$ curl -X OPTIONS "http://jira.mydomain.com/rest/api/latest/search/?jql=issue%20in%20linkedIssues(SR-45)" -v
* Trying 10.107.1.24...
* Connected to jira.mydomain.com (127.0.0.1) port 80 (#0)
> OPTIONS /rest/api/latest/search/?jql=issue%20in%20linkedIssues(SR-45) HTTP/1.1
> Host: jira.mydomain.com
> User-Agent: curl/7.43.0
> Accept: */*
>
* Empty reply from server
* Connection #0 to host jira.mydomain.com left intact
curl: (52) Empty reply from server
This seems to be positive response.
Testing preflight request (OPTIONS) with Crome extention Postman:
OPTIONS http://jira.mydomain.com/rest/api/latest/search/?jql=issue%20in%20linkedIssues(SR-45)
Response error: Could not get any response. This seems to be like an error connecting to http://jira.mydomain.com/rest/api/latest/search/?issue%20in%20linkedIssues(SR-45)
Little bit late to answer this, but I'll leave it here for reference.
In my macro I solved this problem the other way around. Instead of sending a direct request to the JIRA server I used an API exposed by the Confluence server to proxy my JIRA request to the linked JIRA instance.
I described this endpoint in another answer. Using this method you don't break the cross-origin policy. In fact this is what JIRA Issues and JIRA Chart macros use to render their widgets. Quote:
JIRA Proxy
Another nice endpoint is /plugins/servlet/applinks/proxy. It allows forwarding simple REST requests to the linked JIRA instances. For example /plugins/servlet/applinks/proxy?appId={INSERT APPLINK ID HERE}&path=%2Frest%2Fapi%2F2%2Fsearch will call JIRA's issue search REST endpoint and list issues available to the user (as in JIRA search). By "simple request" I mean that only GET and POST HTTP methods are supported in the current version (with POST limited to application/xml and multipart/form-data content types). The servlet supports both query-string and HTTP-header parameters. Check out the source of the servlet in plugin's source to get more info as I haven't found any online documentation for it.
Using this servlet you can get the projects list as well by requesting /plugins/servlet/applinks/proxy?appId={INSERT APPLINK ID HERE}&path=%2Frest%2Fapi%2F2%2Fproject
Servlets's path in the repo is confluence-jira-plugin/src/main/java/com/atlassian/confluence/plugins/jira/AppLinksProxyRequestServlet.java, but most of the important stuff is in its base class confluence-jira-plugin/src/main/java/com/atlassian/confluence/plugins/jira/AbstractProxyServlet.java
-- confluence REST API request while not being admin ends in 401 error
This approach requires JIRA and Confluence instances to be connected through an Application Link though. But I assume you have admin access to both JIRA and Confluence as you are investigating changing the origin policies so it shouldn't be a blocker for you.

How to make an AJAX request to Dictionary.com's REST API using jQuery?

Dictionary.com provides absolutely no documentation on how to grab data from them. I'm trying to use jQuery's ajax requests, but those are not working.
They provide a URL through which I'm supposed to be able to use. I'll provide this below.
http://api-pub.dictionary.com/v001?vid=<VID>&type=random&site=dictionary
They also provide a key, which I assume that I place in the <VID> spot.
Could someone please tell me what I'm doing wrong with this? I'll provide the code I'm using below:
$("#btnGetData").click(function() {
$.ajax({
url: "http://api-pub.dictionary.com/",
type: "GET",
data: "v001?vid=<VID>&type=random&site=dictionary",
success: function() { alert("success") },
});
});
Could someone please tell me what I'm doing wrong?
You are not passing the data correctly. Also the request url is http://api-pub.dictionary.com/v001. Try this:
$("#btnGetData").click(function() {
$.ajax({
url: "http://api-pub.dictionary.com/v001",
type: "GET",
dataType: "jsonp", //For external apis
data: {"vid": <VID>,
"type":"random"
"site": "dictionary"},
success: function() {
alert("success") },
});
});
UPDATE: Maybe you're being blocked by the same origin policy as #thordarson note, in that case add:
dataType: "jsonp" to your ajax call.
Possibility 1
You don't have access to their API. According to their API page they're very selective about who they give access to their API.
We are selective about our API partners and approve use as well as
develop terms on a case-by-case basis. If you are interested in using
our API, please contact us directly [...].
Possibility 2
You're being blocked by the same origin policy. Browsers are generally very strict about requests made by JavaScript across different domains. This can be bypassed using Cross-origin resource sharing. This requires configuring the server you're requesting, so in this case it's not viable.
Your best bet would be to create a server-side script that requests the URL and then using AJAX to request the file.
Example in PHP, let's call this request_dictionary.php:
<?php
$vid = "Your API key";
$type = $_GET['type'];
$site = $_GET['dictionary'];
$request_url = "http://api-pub.dictionary.com/v001?vid=$vid&type=$type&site=$site";
echo file_get_contents($request_url);
?>
Note: You probably need to change this to fit your needs (error handling, 404s, caching etc.). This code is untested.
Then change your jQuery so that it requests your file.
$("#btnGetData").click(function() {
$.ajax({
url: "/request_dictionary.php",
type: "GET",
data: "type=random&site=dictionary",
success: function() { alert("success") },
});
});
Warning
Using an AJAX call without a proxy (as explained in possibility 2) will expose your API key. This is against Dictionary.com's API Terms of Service.
2.1 Dictionary.com will assign and deliver to your Customer Application an Application Key to access the API. All Calls must
contain such Application Key. The Application Key is uniquely
associated with each Customer Application and all versions, upgrades
and updates thereof. The Application Key is Confidential Information
as defined in these Terms and Conditions. You must maintain and keep
the Application Key in a secure, embedded manner not accessible by any
third party. The Application Key is fully revocable by Dictionary.com
at any time. Dictionary.com may block attempts to access the API with
an invalid or revoked Application Key.
I've updated the code in possibility 2 to conceal the API key by keeping it in the PHP file.
Update/Note: Simply passing dataType: 'jsonp' to enable cross-origin calls is not enough. The responding server needs to respond with an Access-Control-Allow-Origin header containing your domain (or a rule that includes your domain). Any configuration of this kind is out of your hand as the requester.
Update/Note 2: Upon investigating the returned headers from your request URL, I can see no evidence of Access-Control-Allow-Origin. This means that even if you had access to their API, you wouldn't be able to access it using AJAX. Full headers below:
GET /v001?vid=%3CVID%3E&type=random&site=dictionary HTTP/1.1[CRLF]
Host: api-pub.dictionary.com[CRLF]
Connection: close[CRLF]
User-Agent: Web-sniffer/1.0.44 (+http://web-sniffer.net/)[CRLF]
Accept-Encoding: gzip[CRLF]
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8[CRLF]
Accept-Language: en-US,en;q=0.8[CRLF]
Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7[CRLF]
Cache-Control: no-cache[CRLF]
Referer: http://web-sniffer.net/[CRLF]

Categories