I want to use Yasgui to run queries against a Stardog knowledge graph.
The request requires specific headers.
Since I only want one tab to query Stardog, I pass a unique configuration object when adding that tab to my front-end.
The query returns the expected results in Chrome but when using Firefox I get an error.
In Firefox developer tools the request I sent using the front-end is listed as 'blocked'. After clicking 'edit and resend' it now works as expected.
//setting required headers in configuration object
requestConfig: {
endpoint: /*[[${triplestoreEndpoint}]]*/ "SparqlEndpointToBeReplacedByThyMeLeaf",
headers: () => ({
Accept:'application/sparql-results+json',
Authorization: 'Basic YWRtaW46YWRtaW4=' // Stardog specific headers with default authentication
}),
method: 'GET'
},
//passing configuration object when adding my custom tab
yasgui.addTab(
false,
{...Yasgui.Tab.getDefaults(), name:name, id:id, requestConfig:requestConfig}
);
I already tried deactivating the CORS policy in my Firefox browser.
Can someone tell me how to configure Yasgui to work with Stardog?
Thanks in advance
Related
I have an App Engine service with a few methods implemented, where I restrict all routes with the login: admin option in the app.yaml.
Making a POST request to my service works:
fetch('http://localhost:8081/api/foo', {
credentials: 'include'});
But making a PUT request fails
await fetch('http://localhost:8081/api/foo', {
credentials: 'include',
method: 'PUT',
body: 'hi there'});
with the following error:
Response to preflight request doesn't pass access control check:
Redirect is not allowed for a preflight request.
I understand this is because my request is somehow not authenticated, and the server redirects my request to the login page. What I don't understand is how to authenticate it.
I'm using webapp2 to process the requests, and setting the following headers:
self.response.headers['Access-Control-Allow-Credentials'] = 'true'
self.response.headers['Content-Type'] = 'application/json'
# This feels wrong, but I still don't clearly understand what this header's purpose is...
self.response.headers['Access-Control-Allow-Origin'] = self.request.headers['Origin']
I think the deeper problem is that I don't undestand how this login feature works (is it cookie based? Why does it work with GET but not PUT? ...), and I don't truly understand CORS either.
Thanks for any help!
So, after discussing with Dan Cornilescu, here is the solution I came up with (Thanks Dan!)
Instead of having my classes inherit webapp2.RequestHandler, they inherit this custom HandlerWrapper.
The big difference is that when receiving an 'OPTIONS' request (ie. preflight), there is no login required. This is what was causing my problem: I couldn't get the preflight request to be authenticated, so now it doesn't need to be.
The CORS is also handled there, with a list of allowed origins
class HandlerWrapper(webapp2.RequestHandler):
def __init__(self, request, response):
super(HandlerWrapper, self).__init__(request, response)
self.allowed_origins = [
r'http://localhost(:\d{2,})?$', # localhost on any port
r'https://\w+-dot-myproject.appspot.com' # all services in the app engine project
]
self.allowed_methods = 'GET, PUT, POST, OPTIONS'
self.content_type = 'application/json'
# login mode: either 'admin', 'user', or 'public'
self.login = 'admin'
def dispatch(self):
# set the Allow-Origin header.
if self.request.headers.has_key('origin') and match_origin(self.request.headers['Origin'], self.allowed_origins):
self.response.headers['Access-Control-Allow-Origin'] = self.request.headers['Origin']
# set other headers
self.response.headers['Access-Control-Allow-Methods'] = self.allowed_methods
self.response.headers['Content-Type'] = 'application/json'
self.response.headers['Access-Control-Allow-Credentials'] = 'true'
# Handle preflight requests: Never require a login.
if self.request.method == "OPTIONS":
# For some reason, the following line raises a '405 (Method Not Allowed)'
# error, so we just skip the dispatch and it works.
# super(HandlerWrapper, self).dispatch()
return
# Handle regular requests
user = users.get_current_user()
if self.login == 'admin' and not users.is_current_user_admin():
self.abort(403)
elif self.login == 'user' and not user:
self.abort(403)
else:
super(HandlerWrapper, self).dispatch()
def match_origin(origin, allowed_origins):
for pattern in allowed_origins:
if re.match(pattern, origin): return True
return False
The login: admin configuration is based on the Users API, available only in the 1st generation standard environment. Not a CORS problem. From the login row in the handlers element table:
When a URL handler with a login setting other than optional
matches a URL, the handler first checks whether the user has signed in
to the application using its authentication option. If not, by
default, the user is redirected to the sign-in page. You can also use
auth_fail_action to configure the app to simply reject requests
for a handler from users who are not properly authenticated, instead
of redirecting the user to the sign-in page.
To use the Users API the user must literally login before the PUT request is made. Make a GET request first, which will redirect you to the login page, execute the login, then make the PUT request.
If that's not something you can achieve then you need to use a different authentication mechanism, not the one based on login: admin.
Update:
The above is true, but rather unrelated as the Users API authentication is addressed - you did mention that some other request method to the same URL works.
The error you get is indeed CORS-related, see Response to preflight request doesn't pass access control check. But I'd suggest not focusing on the accepted answer (which is only about working around CORS), but rather on this one, which is about doing CORS correctly.
I have a React app which calls a Wordpress v5 API.
const api = `${WAPI}`;
const headers = {
'Content-Type': 'application/json'
} ;
fetch(api, {
headers: headers
})
.then(function(data){
console.log(data);
})
.then(this.handleposts)
.catch(err => console.log(err));
}
Which returns this error in my development tools' console:
Access to fetch at 'http://XXX.XXX.XXX.XX/firstcivdivcareers/wp-json/wp/v2/posts/' from origin 'http://localhost:9000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
I used to call a single Wordpress site API but now it doesn't' work. I assumed Wordpress API would work with cross-origin domain calls to be used as a third-party service.
I added changes to the theme's functions.php. When I go to my site in the browser and check the header's in dev tool console. I can see I sent my response with the proper headers. However, doesn't work the same when I call through my JS's fetch call.
Changes added to functions.php:
/**
* Only allow GET requests
*/
function add_cors_http_header(){
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET");
header("Access-Control-Allow-Headers: origin");
}
Locate the file in your wordpress code which is serving the API.
You just have to add at the start of that file:
<? header("Access-Control-Allow-Origin: *"); ?>
Edit:
Instead of editing the core files, the better option is to use the filter as explained in this thread. You can put the following code in your functions.php
add_filter('init', 'add_cors_header');
function add_cors_header() {
header(...);
}
I had this issue as well with my Vue.js code. This is what I added to my GET request and I have had no further issues: https://cors-anywhere.herokuapp.com and it immediately precedes the URL:
let url = 'https://cors-anywhere.herokuapp.com/https://jobs.github.com/positions.json?&markdown=true&page=1';
I hope that helps!
You can use this MS Edge plugin t quickly disable Cors.
CORS Unblock - Microsoft Edge Addons
It will work just fine :)
Meteor js requestPermissions not working. I want to access google calendar, access token not permission with google calendar. How I can get access google calendar.
there are two things to consider. The right permission you need from google, and the API you use to access your data. You don't provide too many details so I don't know whether you need mobile (Cordova) too.
For your project, in Google Developer Console you need to enable the Calendar API. Once you do that, you have options to see what appId / authorization is relevant for your API so you add it to your Meteor Settings.
Then from the OAuth 2.0 scopes you need to select the exact scope you need (search for "calendar" for instance) and add that scope (the entire url) to your array of scopes.
Then you can do GET or POST with something like the native HTTP API of Meteor
example:
let data = HTTP.call('GET', `https://people.googleapis.com/v1/people/me/connections?pageToken=${res.data.nextPageToken}&personFields=emailAddresses`,
// let data = HTTP.call('GET', `https:https://www.googleapis.com/calendar/v3/calendars/{... your calendarId} `,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json'
}
},
(err, res) => { handle these })
I'm trying to use W3C's CSS Validator Web Service API in a Chrome new tab extension. The docs claim that a request is a simple HTTP GET call to a URI, so I figured this should work:
fetch('http://jigsaw.w3.org/css-validator/validator?uri=http%3A%2F%2Fwww.w3.org%2F&profile=css3&output=json')
.then((response) => {
// do stuff with response
});
Unfortunately the promise fails and I get a message like:
Failed to load. No 'Access-Control-Allow-Origin' header is present on
the requested resource. Origin is therefore not allowed access.
How am I supposed to make a "simple" GET request if the resource doesn't allow CORS?
Thanks!
2017-10-22 Update: The change for adding CORS support to the CSS Validator was merged and pushed to production, so the following now works as-is:
const validatorURL = 'https://jigsaw.w3.org/css-validator/validator' +
'?uri=http%3A%2F%2Fwww.w3.org%2F&profile=css3&output=json';
fetch(validatorURL)
.then(response => response.json())
.then(results => console.log(results))
Original answer:
The CSS Validator doesn’t send the necessary CORS response headers. To fix that, I’ve raised a pull request with a change against the CSS Validator sources that’ll enable your code snippet to work as-is. I’ll post an update here once the change is merged and pushed to production.
In the meantime, you can work around the issue by making your request through a CORS proxy:
const proxyURL = 'https://cors-anywhere.herokuapp.com/';
const validatorURL = 'http://jigsaw.w3.org/css-validator/validator' +
'?uri=http%3A%2F%2Fwww.w3.org%2F&profile=css3&output=json';
fetch(proxyURL + validatorURL)
.then(response => response.json())
.then(results => console.log(results))
For details abou why that works, see the How to use a CORS proxy to get around “No Access-Control-Allow-Origin header” problems section of the answer at No 'Access-Control-Allow-Origin' header is present on the requested resource—when trying to get data from a REST API.
You need to register the allowed origin for the extension's manifest:
"permissions": [
"http://jigsaw.w3.org/"
],
And you might need to set the origin mode for the fetch function as well:
fetch(
'http://jigsaw.w3.org/css-validator/validator?uri=http%3A%2F%2Fwww.w3.org%2F&profile=css3&output=json',
{mode: 'no-cors'})
.then((response) => {
// do stuff with response
});
From chrome web store you can add CORS Filter extension. just enable the filter before you run your code.
From here you can add the filter to your chrome browser.
I have generated a consumer key and consumer secret. The website has SSL installed. I have also installed plugins required for JSON and REST services. This is how the url looks like:
https://<url>/wp-json/wc/v1/products
When I am trying to get(GET) the product details using Basic Auth by using POSTMAN, a Chrome plugin, I get a JSON response like:
{
"code": "woocommerce_rest_cannot_view",
"message": "Sorry, you cannot list resources.",
"data": {
"status": 401
}
}
I have both the READ and WRITE permissions corresponding to the Consumer key.
The 401 error you are getting is because you are using basic auth even though your website is not secure (does not have https).
The solution in postman is to use OAuth 1.0. Just add the consumer key and consumer secret and send the request.
I met same problem.
Here is how I solve it:
require "woocommerce_api"
woocommerce = WooCommerce::API.new(
"https://example.com",
"consumer_key",
"consumer_secret",
{
wp_json: true,
version: "wc/v1",
query_string_auth: true
}
)
The key is query_string_auth: true
you need to force basic authentication as query string true under HTTPS
This is how i stopped worrying and moved on.
In short, the woocommerce rest controllers pretty much all have a SOMEWPRESTCLASS::get_item_permissions_check() method which in turn calls wc_rest_check_post_permissions() to decide if it returns that error;
So you hook into that and validate whichever way you want:
add_filter( 'woocommerce_rest_check_permissions', 'my_woocommerce_rest_check_permissions', 90, 4 );
function my_woocommerce_rest_check_permissions( $permission, $context, $object_id, $post_type ){
return true;
}
Trying to help others:
I was struggling with the 401 response while trying to CURL, and also with VBA trying to request as content-type "application/json"
However, I was able to pull a valid response by just entering this in my browser address bar:
https://mywebsite.com/wp-json/wc/v2/products?consumer_key=ck_blahblah&consumer_secret=cs_blahblah
Following this line of thought, I went back to my VBA app and changed the content type to "application/text" and was able to pull a valid response text with response code 200.
Hope this helps someone.
Try this, I had the same issue with the automattic/woocommerce library and I just got it working by appending the customer_key and customer_secret to the query.
$woocommerce->get("customers/$userId?consumer_key={$this->key}&consumer_secret={$this->secret}");
Quick Edit
The above method works but I found a better solution for the automattic/woocommerce library.
Set query_string_auth to true
Had to dig into the code to find this setting.
Found nothing on it in the docs
return new Client($this->url, $this->key, $this->secret, [
"query_string_auth" => true
]);
I just ran into this. Apparently something was funny with how curl was handling the url, so I had to encapsulate it in double quotes.
This doesn't work:
curl https://www.my-site.com/wp-json/wc/v3/orders?consumer_key=ck_40097dbc2844ce7712e1820bcadf0149c2bedegh&consumer_secret=cs_ab57e19263af0b9ab4c596c310f1e7904bb20123
This does work:
curl "https://www.my-site.com/wp-json/wc/v3/orders?consumer_key=ck_40097dbc2844ce7712e1820bcadf0149c2bedegh&consumer_secret=cs_ab57e19263af0b9ab4c596c310f1e7904bb20123"
You can try Oauth 1.0 with postman:
Problem solved by adding this line below to the end of .htaccess file
All you need to add this line to .htaccess , this work with me
SetEnv HTTPS on
And make sure use OAuth 1.0 for Authorization
Try making the request using query parameter, like this:
https://www.exemple.com/wp-json/wc/v3/orders?consumer_key=ck_01234567890&consumer_secret=cs_01234567890
here: https://www.exemple.com you'll need to fill your url domain.
here: consumer_key and consumer_secret is your ck and cs that was previous genereted on WooCommerce > Settings > Advanced > REST API
Here is a modified answer to Quickredfox's anwer:
add_filter('woocommerce_rest_check_permissions', 'my_woocommerce_rest_check_permissions', 90, 4);
function my_woocommerce_rest_check_permissions($permission, $context, $object_id, $post_type) {
if($_GET['consumer_key'] == 'asdfghj' && $_GET['consumer_secret'] == 'qwerty') {
return true;
}
return $permission;
}
The downside to this is that the flexibility of adding and revoking access for users using a gui is lost. However, if nothing else works and you just can't figure out why, this will work and does not expose the API to the whole world.
Oh, and this requires passing the key and secret as parameters a la:
https://foo.bar.com/wp-json/wc/v3/products/123&consumer_key=asdfghj&consumer_secret=qwerty
This will work without https, but if you use it without https, remember that any credentials you send along with your request will be sent in plain text.
I just ran into this, I was getting the exact same error message as OP. I was using https and OAuth 1. The problem ended up being the domain. I was trying to access example.com when the correct domain for the site was www.example.com.
This URL returns 401 woocommerce_rest_cannot_view error:
https://example.com/wp-json/wc/v3/products
This URL works and returns results:
https://www.example.com/wp-json/wc/v3/products
For local development (localhost) you can also use Basic Auth (e.g. for Postman) instead of Consumer Key & Consumer Secret. It works seamlessly.
Add this code to function.php to fix the problem:
add_filter( 'woocommerce_rest_check_permissions', 'my_woocommerce_rest_check_permissions', 90, 4 );
function my_woocommerce_rest_check_permissions( $permission, $context, $object_id, $post_type ){
return true;
}
in node js code would be
const WooCommerceRestApi = require("#woocommerce/woocommerce-rest-api").default;
const api = new WooCommerceRestApi({
url: "http://example.com",
consumerKey: "ck_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
consumerSecret: "cs_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
queryStringAuth: true,
version: "wc/v3"
});
It's sometimes an error with wordpress htaccess configuration (only if you are accessing website by https).
For some reason woocommerce want you to authorize with basic authentication when your are connecting through https which some hosting blocks so you need to unlock it.
you need to change
RewriteRule ^index\.php$ - [L]
To
RewriteRule ^index\.php$ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]