Domino, CORS and the OPTIONS request - xpages

I'm working on an AngularJS app that uses Domino as a backend. Since I want more customization options than Domino Access Services (DAS) gives me, my next choice was the REST Service from the Extension Library.
The app is running on a separate domain from Domino, so I need to add CORS headers to make that scenario work. With CORS, the browser (for some requests) first makes a preflight HTTP OPTIONS request to the server to check what methods are allowed (more on CORS here: http://www.html5rocks.com/en/tutorials/cors/).
The problem I now run into is that Domino throws a Method Not Allowed error (response code 405) on that OPTIONS request. I already added it to the list of allowed methods in my internet site document (although I'm not sure if the REST service will honor that at all). The request comes through fine with DAS.
Looking at the source code of the RestDocumentJsonService in the Extension Library it seems that the OPTIONS method isn't supported at all.
Any thoughts on how to make this work? Or for a workaround? I know that I can write my own servlet or install a proxy in front of Domino, but I don't want to go that route (yet ;-)

If you are trying to use Authenticated CORS you will need minimum four headers to work
Access-Control-Allow-Credentials: true
access-control-allow-header: X-Requested-With, Origin, Accept, Accept-Version, Content-Type
access-control-allow-method: OPTIONS, GET, PUT, POST, DELETE, PATCH
access-control-allow-origin: http://yourOtherDomain.com
Unfortunately you can only add 3 headers through the Web Site documents
You cannot add anything through a Phase Listener because the ExtLib Rest Services do not go through the XSP Phases
You can use a proxy such as nginx or in my case I used IHS
http://xomino.com/2014/04/20/adding-custom-http-headers-to-domino-r9-using-ibm-http-server-ihs/
Or you can just roll your own REST service and add whatever headers you want

Mark, just a quick comment. I am not sure if this would work for you.
But what I do in a current project is to put the Angular app in the WebContent folder of the NSF. This serves several purposes - one of them being ease of deployment with the right version of the backend code in the same NSF. I have set the database up for source control and edit the Angular part directly in the on-disk project of the NSF and just sync them when I need to run it. As a side effect this setup will also solve any CORS issues as client side code is launched from the same domain as my REST service is called from ;-)
/John

Related

Is it possible to update parts/directives in the "content-security-policy" header using DeclarativeNetRequest API?

I am in the process of migrating from Manifest V2 to V3, from Web Request API to Declarative Net Request API. Using Web Request, I modify the "content-security-policy" header by adding a domain into the list of various directives (default-src, frame-src, etc). I tried using the "append" operation in the rule action. Is it possible to target a directive? What if the directive does not exist? Does append just add the supplied string to the end? With Web Request, I was able to examine each directive and update each accordingly, before returning the new value. This allowed me to inject a script that is needed into each frame.
Instead, would it be possible to continue to use the Web Request API with V3? In my setup, I have my chrome extension "Published - unlisted". I do use the force install option when deploying the extension to our internal users, and the only reason I have it unlisted and not private is so that the users who have the extension can get updated whenever a new version is released. Would it be possible to have users updated without having the extension listed? Perhaps by hosting the extension in my own server? Please advise on what can be done to have the ability to update the response header, specifically the "content-security-policy" header the way I have done before, and whether I can continue to use Web Request API going forward (using V3). In the Chrome dev website, there's a mention about continuing to use Web Request if force install is used, and only if its "deployed to a given domain or to trusted testers", but I'm not sure what that actually means. What would I need to do to meet the criteria?
I tried using the append operation in the rule action via the Declarative Net Request API, but its not working as expected. I dont see the security policy being updated when I inspect the response header in dev tools. I also get errors stating that many scripts, images, etc violate the security policy for websites that did not have one to begin with (My extension targets any website).

The HTTP method is not allowed for the specified URL

We would like to use PUT, PATCH and DELETE methods when building our internal API in Domino, but I can't configure those methods. Server refusing to pass them.
When I used method PUT Domino replied to me:
Error code: 405 | Request method is not allowed by the server
After that I enabled methods via notes.ini
HTTPEnableMethods=GET,POST,PUT,DELETE,HEAD,PATCH
That seems to help a bit but now it says something about URL, but I do not really get what it means.
Error code: 405 | The HTTP method is not allowed for the specified URL
I have made tests on two different setups: with and without internet sites documents enabled in server documents.
Does anybody what I need to do to solve the problem above?
UPDATE
I just noticed a help text on Internet Site for "Methods" field.
GET, HEAD, and POST are the most commonly used methods. OPTIONS and TRACE are useful for debugging. PUT and DELETE should only be enabled if the Web site includes special CGI programs or Java applications that implement them.
Based on that it seems it is not possible to make PUT and DELETE work out of the box.

Can a REST API works as a PROXY for CORS issues?

My problem is as follows :
I'm developping a web application with Angular. Angular application runs on the client's browser. In its logic, my application needs data from other-domain.com.
I can't use directly XMLHttpRequest() because of CORS policy problems. (The web server other-domain.com producing data is not my domain and cannot add 'Control-Access-Allow-Origins')
So instead of having :
Angular ===>> other-domain.com (forbidden because of CORS)
I'm creating a REST API that will get data from other-domain.com and wraps this data with header 'Access-Control-Allow-Origin' : '*' before sending to client's Angular.
So my workflow becomes :
Angular ==>> my API server ==>> other-domain.com (allowed because request for other-domain does not execute on the browser)
Do you think my idea works well forevery request (GET, POST, adding cookies header) ? In that case the API I'm developping acts as a proxy, right ?
Thank you
Short answer: yes. In fact, there's packages and sites out there that will do this for you.
But I think another question is why you have the need to circumvent CORS restrictions. After all, it is working as intended and there's a reason for its existence in the first place.
If you have a backend already, can you add an endpoint where your backend will make the call to the other domain, and leave the browser to communicate only within your domain?
If you're only doing RESTful GETs and an opaque request (no credentials, no cookies, etc.) will suit your needs, you could also just use the fetch api with {mode: 'no-cors'}; however, you'd need to 'circumvent' the HttpClient to do so and you'd need a polyfill if you need to support IE.

Emitting node.js views and scripts as snippets

I have built a node.js app for which i would like to realize "snippets" to be included in external web applications. It means that i must create some javascript scripts to be included and called from external apps that call a node.js view and its scripts/css .
Does node.js provide a way to do it natively or do i have to create the script that embeds the view and the related client libraries?
enable cross-origin resource sharing:
Cross-Origin Resource Sharing (CORS) is a specification that enables truly open access across domain-boundaries. If you serve public content, please consider using CORS to open it up for universal JavaScript/browser access.
Must read: http://enable-cors.org/#how-expressJS
Important stuff:
Access-Control-Allow-Origin
Access-Control-Allow-Headers
Sounds like components might be your answer:
https://github.com/component/component
http://tjholowaychuk.com/post/27984551477/components
I hope I understand your question - You want to display an html-like snippet on a different site.
One way of doing it is to provide an API, but it will probably be a
JSON API, and the other site will have to display it on its own
(somebody already noted CORS is needed for this). You could just serve a JSON with html in it (though you need to make sure the other app doesn't escape it)
You could have your server serve an image (like they do in travis CI), but then the other site will show it as an image (copy paste the text won't be possible)
You could use Iframe, serving an html to this other site.
There's the possibility you meant something totally different, like reusing your server an client code - in that case I recommend http://browserify.org, or the already mentioned component.js.

XMLHttpRequest succeeds without manifest permissions? Maybe CORS?

I have developed a Google Chrome extensions that uses YouTube Data API v2. My permission field in the manifest looks like this, because the script is injected in pages under youtube.com and I also need access to tabs:
"permissions": ["tabs", "*://*.youtube.com/*"]
This also works when I do a request to YouTube Data API v2 because the request is done to http://gdata.youtube.com/, so it is the same domain. But now I am migrating to YouTube Data API v3, and the requests must be done to http://www.googleapis.com/youtube/v3/ (note HTTPS instead of HTTP also). However, surprisingly, my requests are working perfectly without adding any new permission.
I know, I am asking something that doesn't seem to be a problem, but personally I consider any behavior that I don't understand in my software a problem. Why does this happen? Am I not supposed to add a permission such as "*://*.googleapis.com/*" in order for my XMLHttpRequest requests to the API to work?
I also have some king of guess about this: HTTP Access Control headers. My requests do send a Origin header with value chrome-extension://myExtensionId. And the answer from the API also contains the following header:
Access-Control-Allow-Origin: chrome-extension://myExtensionId
But could this be the reason Chrome is allowing me to do a cross-origin XMLHttpRequest without any extra permission defined in the manifest? Not sure, and apparently this is not documented anywhere in Google APIs, YouTube Data API v3 or Chrome Extensions developer documentation.
If Chrome does not find the permission in the manifest, it treats a request as a normal request. This means that a request will still succeed when the right CORS headers are set. Otherwise, a request will fail because of the same origin policy.
The Google API JavaScript library explicitly mentions support for CORS:
Making a request: Option 3
Google APIs support CORS. Please visit the CORS page for more information on using CORS to make requests.
If possible, I still recommend adding the permission to the manifest file. For simple requests, this does not bring any advantages. For non-simple requests, this will half the number of requests: Non-simple requests are always preceeded by a preflight (OPTIONS) request which checks if the client is permitted to access the source.
By adding the permission to the manifest file, Chrome will not fall back to CORS, and always use one network request to complete the request. Great!
However... you might think again if you're the author of an already-deployed extension. When new origin permissions are added to the manifest file, the extension will be disabled until the user approves the extension. The dialog box shows "Remove extension" and "Enable" next to each other, so there's a chance of loosing the user.
If you wish, you can overcome this problem by using an optional permission, activated at the options page. Clearly explain in layman language that the option will improve the speed of the extension, and don't forget to mention that additional permissions will be requested.

Resources