Has anyone an idea about IBM OpenWhisk and Cors settings? - node.js

i have the following problem. When run my openWhisk function through the API gateway all is fine. Also calling it as a cross domain request works well.
But i need to call it with credentials and it seems there is no option to do this.
What i tried:
just enabling the API CORS setup without any headers in the function itself
enabling cors in the API und having CORS headers in the function as well ->the relevant headers (access-origin) in the function get overwritten!
disabling CORS in the API and having CORS headers in the function -> the relevant headers (access-origin) of the function get deleted
This is the code that normally should work:
return {
headers: {
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Origin': domain,
'Access-Control-Allow-Credentials': 'true',
'Content-Type': 'text/xml'
},
body: xml
}
Would be great if anyone has an idea because the support is not answering my ticket for many days now.
Thanks and best, André

Using your sample:
> cat t.js
function main() {
return {
headers: {
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Origin': 'domain',
'Access-Control-Allow-Credentials': 'true',
'Content-Type': 'text/xml'
},
body: "<hi></hi>"
}
}
Against Bluemix:
> wsk action update t t.js -a web-custom-options true --web true
ok: updated action t
And curling the web action
> curl -v https://openwhisk.ng.bluemix.net/api/v1/web/myspace/default/t.http
< HTTP/1.1 200 OK
< X-Backside-Transport: OK OK
< Connection: Keep-Alive
< Transfer-Encoding: chunked
< Server: nginx/1.11.13
< Date: Tue, 18 Jul 2017 14:00:40 GMT
< Content-Type: text/xml
< Access-Control-Allow-Headers: *
< Access-Control-Allow-Origin: domain
< Access-Control-Allow-Credentials: true
<hi></hi>
Without the annotation:
> wsk action update t t.js -a web-custom-options false --web true
Repeating the curl will show these headers:
< Access-Control-Allow-Origin: *,domain
< Access-Control-Allow-Methods: OPTIONS, GET, DELETE, POST, PUT, HEAD, PATCH
< Access-Control-Allow-Headers: Authorization, Content-Type,*
< Access-Control-Allow-Credentials: true

Related

CouchDB, EventSource and OPTIONS method (405 Method Not Allowed)

I would like to implement Event Source feed of _changes for some documents in publicly readable database in CouchDB. Unfortunately, I get 405 error and:
Access to fetch at 'https://COUCHDOMAIN:6984/DBNAME/_changes?feed=eventsource&filter=_doc_ids&doc_ids=[%22DOCID%22]&since=now&include_docs=true&heartbeat=44000' from origin 'https://CLIENTDOMAIN' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
I do not understand why I get Allow: GET,POST,HEAD in response while in CORS config, there is also OPTIONS... EventSource constructed with withCredentials: true/false, no difference...
I will appreciate any suggestion.
My CORS configuration:
[cors]
origins = https://CLIENTDOMAIN
headers = accept, authorization, content-type, origin, referer
methods = GET, PUT, POST, HEAD, DELETE, OPTIONS
credentials = true
Request Headers:
OPTIONS /DBNAME/_changes?feed=eventsource&filter=_doc_ids&doc_ids=[%22DOCID%22]&since=now&include_docs=true&heartbeat=44000 HTTP/1.1
Host: COUCHDOMAIN:6984
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: GET
Access-Control-Request-Headers: cache-control
Origin: https://CLIENTDOMAIN
User-Agent: Mozilla/5.0 (Linux; Android 10; LM-V405) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
Sec-Fetch-Dest: empty
Referer: https://CLIENTDOMAIN/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,pl-PL;q=0.8,pl;q=0.7,en-US;q=0.6
Response Headers:
HTTP/1.1 405 Method Not Allowed
Access-Control-Allow-Origin: https://CLIENTDOMAIN
Access-Control-Expose-Headers: content-type, cache-control, accept-ranges, etag, server, x-couch-request-id, x-couch-update-newrev, x-couchdb-body-time
Allow: GET,POST,HEAD
Cache-Control: must-revalidate
Content-Length: 69
Content-Type: application/json
Date: Fri, 11 Feb 2022 20:04:06 GMT
Server: CouchDB/3.2.1 (Erlang OTP/20)
X-Couch-Request-ID: ab68310597
X-CouchDB-Body-Time: 0
General (from chrome dev tools):
Request URL: https://COUCHDOMAIN:6984/DBNAME/_changes?feed=eventsource&filter=_doc_ids&doc_ids=[%22DOCID%22]&since=now&include_docs=true&heartbeat=44000
Request Method: OPTIONS
Status Code: 405 Method Not Allowed
Remote Address: COUCHIP:6984
Referrer Policy: strict-origin-when-cross-origin
Solution (inspired by: https://stackoverflow.com/a/50914749/2626200):
[cors]
origins = https://CLIENTDOMAIN
headers = accept, authorization, content-type, origin, referer, cache-control
...

Python requests too slow compared to Postman or cURL

I am trying to make a single API call using different approaches in Python3 but they are all incredibly slow if I compare with the same request in Postman and/or cURL.
This is what I am trying:
headers = {
"Authorization": "Bearer " + self.access_token,
"Content-Type": "application/json",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Accept": "*/*",
"User-Agent": "PostmanRuntime/7.28.2",
"Cache-Control": "no-cache"
}
session = requests.Session()
api_res = session.get(self.api_endpoint, headers=headers, timeout=self.req_timeout,)
When running this call, it gets stuck for a few minutes until I receive a response. If I use Postman for example, I get the result in 1 second or less.
I also tried using http.client, urllib3 but I still see a huge delay in the call.
I also tried debugging the call:
import http.client
http.client.HTTPConnection.debuglevel = 1
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
Debug response:
[DEBUG] Starting new HTTPS connection (1): ...:443
header: Content-Type: application/json; charset=utf-8
header: Content-Length: 61
header: Connection: keep-alive
header: Date: ...
header: Cache-Control: no-cache
header: Pragma: no-cache
header: Expires: -1
header: WWW-Authenticate: Bearer
header: Access-Control-Allow-Origin: *
header: P3P: CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
header: Access-Control-Allow-Methods: GET, POST, OPTIONS, HEAD
header: X-XSS-Protection: 1; mode=block
header: Access-Control-Allow-Headers: accept, authorization, content-type, Cache-Control, P3P, GE-IGNORE-CACHE, Signature, fromMobile, ssoToken, fromAdmin, fromGameapp, fromGtv, fromGameapp, ManagerOrgUnitUserName, ManagerOrgUnitId, g-s-x, g-s-x-t, g-s-i-i, User-Agent, Referer, Origin, Access-Control-Allow-Headers
header: X-Content-Type-Options: nosniff
header: X-XSS-Protection: 1; mode=block
header: Referrer-Policy: same-origin
header: Strict-Transport-Security: max-age=31536000; includeSubDomains
header: X-Cache: Error from cloudfront
header: Via: 1.1 ....cloudfront.net (CloudFront)
header: X-Amz-Cf-Pop: ORD52-C1
header: X-Amz-Cf-Id: ...
Any ideas about why is it so slow? What it doesn't happen when I replicate to Postman for example?
Even from Google is taking a lot of time:
requests.get("https://www.google.com")
I also realized that it's working with ipv4 and NOT with ipv6.
Thanks!
I found out that IPv6 was not working but IPv4 was. I had to force calls to IPv4 like this:
import socket
import requests.packages.urllib3.util.connection as urllib3_cn
urllib3_cn.allowed_gai_family = lambda: socket.AF_INET

recreating cURL request with -I, -H flags in nodeJS

On the command line, I can do a request like: curl -I -H "Fastly-Debug: 1"
and it will return a lot of helpful information from the CDN serving that URL, in this case, Fastly:
cache-control: public, max-age=0, must-revalidate
last-modified: Tue, 20 Apr 2021 21:17:46 GMT
etag: "4c5cb3eb0ddb001584dad329b8727a9a"
content-type: text/html
server: AmazonS3
surrogate-key: /v3.6/tutorial/nav/alerts-and-monitoring/
accept-ranges: bytes
date: Fri, 30 Apr 2021 20:50:15 GMT
via: 1.1 varnish
age: 0
fastly-debug-path: (D cache-lga21923-LGA 1619815815) (F cache-lga21940-LGA 1619815815)
fastly-debug-ttl: (M cache-lga21923-LGA - - 0)
fastly-debug-digest: 04c3e527819b6a877de6577f7461e132b97665100a63ca8f667d87d049092233
x-served-by: cache-lga21923-LGA
x-cache: MISS
x-cache-hits: 0
x-timer: S1619815815.944515,VS0,VE136
vary: Accept-Encoding
content-length: 65489
How can I do this in node?
This is my attempt:
const headers = {
'Fastly-Key': environment.getFastlyToken(),
'Accept': 'application/json',
'Content-Type': 'application/json',
'Fastly-Debug': 1
};
async retrieveSurrogateKey(url) {
console.log("this is the url: ", url)
try {
request({
method: `GET`,
url: url,
headers: headers,
}, function(err, response, body) {
if (err){
console.trace(err)
}
console.log(request.headers)
})
} catch (error) {
console.log("error in retrieval: ", error)
}
}
Is there a way for me to pass in the -I and -H flags?
The -H (header) flag allows you to specify a custom header in cURL. Your code already does this - great! All that's left is emulating the -I (head) flag.
From cURL manpage for the -I option:
Fetch the headers only! HTTP-servers feature the command HEAD which this uses to get nothing but the header of a document.
To use the HEAD method, you need to specify it instead of GET:
method: `HEAD`
And finally, the headers returned by the server in the response can be obtained from response.headers.

Getting the API Key from ServiceStack request

Have a simple get Customer api that's returning list of customers fine.
Setting up for service to service authentication, if I make this [Authenticated] and try to implement using ApiKeyAuthProvider, the req.GetApiKey returns null and I get an error;
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST https://localhost:44347/api/customers application/json 0
Microsoft.AspNetCore.Hosting.Internal.WebHost:2019-07-01 16:50:34,004 [16] INFO Microsoft.AspNetCore.Hosting.Internal.WebHost - Request starting HTTP/1.1 POST https://localhost:44347/api/customers application/json 0
The thread 0x42cc has exited with code 0 (0x0).
The thread 0x302c has exited with code 0 (0x0).
ServiceStack.ServiceStackHost:2019-07-01 17:01:14,601 [16] ERROR ServiceStack.ServiceStackHost - ServiceBase<TRequest>::Service Exception
System.ArgumentOutOfRangeException: Length cannot be less than zero.
Parameter name: length
at System.String.Substring(Int32 startIndex, Int32 length)
at ServiceStack.Host.HttpRequestAuthentication.GetBasicAuth(IRequest httpReq) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\HttpRequestAuthentication.cs:line 45
at ServiceStack.Host.HttpRequestAuthentication.GetBasicAuthUserAndPassword(IRequest httpReq) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\HttpRequestAuthentication.cs:line 50
at ServiceStack.Auth.ApiKeyAuthProvider.PreAuthenticate(IRequest req, IResponse res) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Auth\ApiKeyAuthProvider.cs:line 232
at ServiceStack.AuthenticateAttribute.PreAuthenticate(IRequest req, IEnumerable`1 authProviders) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\AuthenticateAttribute.cs:line 96
at ServiceStack.AuthenticateAttribute.ExecuteAsync(IRequest req, IResponse res, Object requestDto) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\AuthenticateAttribute.cs:line 74
at ServiceStack.Host.ServiceRunner`1.ExecuteAsync(IRequest req, Object instance, TRequest requestDto) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\ServiceRunner.cs:line 127
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 640574.8754ms 400 application/json; charset=utf-8
Microsoft.AspNetCore.Hosting.Internal.WebHost:2019-07-01 17:01:14,607 [16] INFO Microsoft.AspNetCore.Hosting.Internal.WebHost - Request finished in 640574.8754ms 400 application/json; charset=utf-8
Clearly I have missed something obvious...any pointers appreciated.
// Register ORMLite connection
container.Register<IDbConnectionFactory>(dbFactory);
//Tell ServiceStack you want to persist User Auth Info in SQL Server
container.Register<IAuthRepository>(c => new OrmLiteAuthRepository(dbFactory));
// See https://docs.servicestack.net/api-key-authprovider
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new ApiKeyAuthProvider(AppSettings) {
SessionCacheDuration = TimeSpan.FromMinutes(10),
AllowInHttpParams = true, // Whether to allow API Keys in 'apikey' QueryString or FormData (e.g. `?apikey={APIKEY}`)
RequireSecureConnection = true,
},
}
) {
IncludeRegistrationService = true,
});
GlobalRequestFilters.Add((req, res, dto) =>
{
LastApiKey = req.GetApiKey();
});
Request
POST https://localhost:44347/api/customers HTTP/1.1
Host: localhost:44347
Connection: keep-alive
Content-Length: 2
Accept: application/json
Origin: https://localhost:44347
Authorization: yDOr26HsxyhpuRB3qbG07qfCmDhqutnA-yDOr26HsxyhpuRB3qbG07qfCmDhqutnA-yDOr26HsxyhpuRB3qbG07qfCmDhqutnA
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Content-Type: application/json
Referer: https://localhost:44347/swagger-ui/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8
{}
Response
HTTP/1.1 400 ArgumentOutOfRangeException
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Vary: Accept,Origin
Server: Microsoft-IIS/10.0
X-Powered-By: ServiceStack/5.50 NetCore/Windows
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
Access-Control-Allow-Headers: Content-Type
X-Startup-Errors: 1
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Content-Disposition
X-SourceFiles: =?UTF-8?B?QzpcUmVwb3NcTUJXZWJccnZhcGlcUnZXZWJcUnZBcGlcYXBpXGN1c3RvbWVycw==?=
X-Powered-By: ASP.NET
Date: Wed, 03 Jul 2019 08:07:40 GMT
13e
{"responseStatus":{"errorCode":"ArgumentOutOfRangeException","message":"Length cannot be less than zero.\r\nParameter name: length","errors":[{"errorCode":"ArgumentOutOfRangeException","fieldName":"length","message":"Length cannot be less than zero.\r\n"}]},"responseCreatedUtcDateTime":"2019-07-03T08:07:40.7955827Z"}
0
Your client is sending an invalid Authorization Bearer Token, it needs to have the Authroization Bearer Token format:
Authorization: Bearer {Token}
If you're sending an Authenticated API Key or JWT Request via Open API it needs to have the Bearer prefix as per the Open API docs:
OK I had manually created a User and APIKey in the underlying tables and had used a UserAuthId 'SomeAuthId' i.e. letter in them, and the ORM repository code is expecting these to be integers. Its cool that I can see the code in github and debug this myself - thanks for the comment as it got me thinking and looking into my Auth setup.

How to properly serve static assets with Hapijs

I'm trying to get Fastly pointed at my heroku instance that is running hapijs and serving static files from /assets/. I have a route setup that looks like this:
// Assets
{
method: "GET",
path: "/assets/{path*}",
config: {
cache: {
privacy: 'public',
expiresIn: 31536000000 // 1 year in milliseconds
}
},
handler: {
directory: { path: './public/assets'}
}
},
Here are the headers sent back on each request:
HTTP/1.1 200 OK
content-type: text/css; charset=utf-8
last-modified: Thu, 22 Jan 2015 07:08:07 GMT
etag: "9c7d48799e5230b7c97ef1978b81ad533c10b950"
set-cookie: csrf=xyz; Path=/
set-cookie: session=xyz; Path=/
cache-control: max-age=31536000, must-revalidate, private
Date: Thu, 22 Jan 2015 07:21:15 GMT
Connection: keep-alive
How do I not set cookies on the responses from this enpoint and why does the cache-control header set must-revalidate and private. Shouldn'it just be public?
I finally solved this issue. I had a few plugins that were setting cookies: yar, hapi-auth-cookie, and crumb. Unfortunately there is not yet any standard way of removing plugins from a particular route.
crumb allows you to add a skip function to the registration options that will disable it.
auth let's you disable it at the route config by setting auth: false.
yar doesn't yet have any mechanism for doing this so I submitted a PR to fix it
You can also remove cookies via Fastly, before the response is considered to be stored in the cache. For this you need to do the following configuration steps:
Content -> Headers:
Name Remove Set-Cookie from /assets
Type: Cache
Action: Delete
Destination: http.Set-Cookie
On that newly generated Header Configuration: Settings -> Cache Conditions ->
New
Name: /assets
Apply If: req.url ~ "^/assets/"
That will remove the Set-Cookie header before it's "seen" by Fastly and will thus make it cachable.

Resources