I tried several approach to match this specific pattern of the url:
https://app.launchdarkly.com/sdk/goals/123123123
so the 123123123 will be always changing.also for some reason its making a OPTION call beside another GET call every time. Not sure why and that's likely another story...
nock return error like:
Error: Error: Nock: No match for request {
"method": "OPTIONS",
"url": "https://app.launchdarkly.com/sdk/goals/123123123",
"headers": {
"origin": "http://localhost",
"access-control-request-method": "GET",
"access-control-request-headers": "X-LaunchDarkly-User-Agent",
"user-agent": "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/16.5.3",
"host": "app.launchdarkly.com",
"content-length": 0
}
}
nock is not recognizing the pattern if I do (note that I am copying the same pattern as a GET as well)
nock('https://app.launchdarkly.com')
.persist()
.defaultReplyHeaders({
'access-control-allow-origin': '*',
'access-control-allow-headers': '*',
'access-control-allow-credentials': 'true',
})
.options('/sdk/goals.*$/')
.reply(200, mockLDExperiments);
or
nock('https://app.launchdarkly.com')
.persist()
.defaultReplyHeaders({
'access-control-allow-origin': '*',
'access-control-allow-headers': '*',
'access-control-allow-credentials': 'true',
})
.options('/sdk/goals/**/*')
.reply(200, mockLDExperiments);
or
nock('https://app.launchdarkly.com')
.persist()
.defaultReplyHeaders({
'access-control-allow-origin': '*',
'access-control-allow-headers': '*',
'access-control-allow-credentials': 'true',
})
.options('/sdk/goals')
.reply(200, mockLDExperiments);
any idea how to write the correct path matcher so I can allow this segment scenario gets picked up by nock?
Nock supports Regex path matching. It seems you're attempting something similar with globs, however, if a string is provided Nock only does exact matching.
Docs
For your case, something like this should get you going.
nock('https://app.launchdarkly.com')
...
.options(/^\/sdk\/goals\//)
...
Related
I'm trying to run an XML post using node-fetch but I get this error:
org.xml.sax.SAXException: No deserializer for {http://www.w3.org/2001/XMLSchema}anyType
Here is the body I send:
<soapenv:Body>
<e:getXMLListObject>
<table>Enterprise</table>
<fields>
<item>EntCorpName</item>
<item>EntAcronym</item>
<item>EntSiren</item>
<item>EntSiret</item>
<item>EntAd1</item>
<item>EntZip</item>
<item>EntCity</item>
</fields>
<query>
<item>
<item>Entid = '001152000000'</item>
</item>
</query>
</e:getXMLListObject>\n
</soapenv:Body>
An idea please, this is the first time I use this type of body (table) for the others, it works very well.
The code: await fetch(url,options).then(response => {...}
I put this xml in the body parameter in options with soapenv:Envelope ofc.
let options = {
method: 'POST',
body: xml,
timeout: 10000,
credentials: 'include',
headers: {
'Content-Type': 'text/xml;application/x-www-form-urlencoded;charset=UTF-8',
'Content-Length': xml.length,
'Accept': 'text/xml',
'Access-Control-Allow-Credentials': true,
'Access-Control-Allow-Origin': true,
'soapaction': 'add',
"Access-Control-Expose-Headers":"Authorization",
"Cookie": cookies
}
};
NB : Is a client Xml.
I'm trying to convert this cURL command into a request with AXIOS
`curl -X POST "https://serverless-upload.twilio.com/v1/Services/${service_uid}/Functions/${function_uid}/Versions" \
-F "Content=#./template_scripts/collect.js; type=application/javascript" \
-F "Path=collect.js" \
-F "Visibility=public" \
-u "${client.accountSid}:${client.password}"`
my attempt at doing so looks like this:
collect_file = ""
await axios.get("https://pastebin.com/raw/RFYs4n2p").then((r) => collect_file = r.data)
url = `https://serverless-upload.twilio.com/v1/Services/${service_uid}/Functions/${function_uid}/Versions`
form = new FormData();
form.append("Path", "collect");
form.append("Visibility", "public");
form.append("Content", collect_file);
form.append("filename", "collect.js");
form.append("contentType", "application/javascript");
await axios.post(url, form, {
headers: {
Authorization: 'Basic ' + Buffer.from(`${accountSid}:${authToken}`).toString('base64'),
...form.getHeaders(),
},
})
When filling the "Content" param I'm using the text representation of a JS file that I have hosted on Pastebin. In the initial cURL command you see I specify the file ./template_scripts/collect.js I don't want to use fs to load the "collect.js" file as I want the code to not use the file system.
The error I get is
Error: Request failed with status code 400
{
message: 'Invalid function version content.',
code: 20001,
user_error: true,
http_status_code: 400,
params: {}
}
400
{
date: 'Wed, 10 Feb 2021 13:39:08 GMT',
'content-type': 'application/json',
'content-length': '113',
connection: 'close',
't-request-id': 'RQ1bf727ce267b5b974cd1eeab122ad02e',
'x-shenanigans': 'none',
'access-control-allow-origin': '*',
'access-control-allow-headers': 'Accept, Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since',
'access-control-allow-methods': 'GET, POST, DELETE, OPTIONS',
'access-control-expose-headers': 'ETag',
'access-control-allow-credentials': 'true',
'x-powered-by': 'AT-5000',
'x-home-region': 'us1',
'x-api-domain': 'serverless-upload.twilio.com',
'strict-transport-security': 'max-age=31536000'
}
I'm assuming the problem may be with using the text version of the JS file but not entirely sure. When read from pastebin it is returned as type "string".
Thank You!
Place the filename as the third argument for "Content" param
form.append("Content", collect_file, "collect.js");
I am having trouble sending JSON data that contains special characters like ` to my Node Express server.
I posted How can I render UTF-8 characters in JSX without using dangerouslySetInnerHTML in 2020 earlier, but I think I am approaching the problem incorrectly.
The Problem:
When I submit my JSON form data using an HTTP Client, my req.body HTMLifies special characters:
// Sending a nested JSON.stringified Object
const response1 = await fetch(
`${baseUrl}/chhands/${granthState.lastChhand.id}/pauris`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
pauri: formattedTuk,
last_pauri_id: granthState.lastPauri?.id,
}),
}
);
Here is a result of the console.logging {pauri: formattedTuk, last_pauri_id: granthState.lastPauri?.id}:
What it looks like on the backend when I submit the nested JSON object:
Here is where the where I am even MORE confused:
Here, instead of sending a nested object, I only send the formattedTuk [Array] object, which looks like:
[
{
line_number: 1,
content_unicode: 'ਆਪ ਅਛਤ ਸਮਰੱਥ ਪ੍ਰਭੁ ਦਈ ਬਡਾਈ ਨਾਮ ।',
content_gs: 'Awp ACq smr`Q pRBu deI bfweI nwm [',
content_transliteration_english:
"aap achhat samara'th prabh dhiee baddaiee naam |",
first_letters: 'ਆਅਸਪਦਬਨ',
thamkis: [],
vishraams: [],
},
];
// Sending the raw array object stringified {}
const response2 = await fetch(
`${baseUrl}/chhands/${granthState.lastChhand.id}/pauris`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formattedTuk),
}
);
What it looks like on the backend when I submit the ONLY the Array Object:
Other things I've tried:
Used Axios (instead node-fetch) and it gave the same effect
Used POSTMAN and it had the same effect
Double checked my Content-Type and charset but it all looks good.
Here is my Express middleware settings. I was using body-parser before, but it seems that express.json() is giving me the same effect. I've also seen people recommend using qs.stringify() but what I am doing seems fairly simple.
app.use(morgan('tiny'));
app.use(helmet());
app.use(express.json());
app.use(cors());
Updates:
Here is the exact "Copy as Fetch" value:
fetch("http://localhost:1469/api/v1/chhands/53/pauris", {
"headers": {
"accept": "*/*",
"accept-language": "en-US,en;q=0.9",
"content-type": "application/json",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-site"
},
"referrer": "http://localhost:3000/",
"referrerPolicy": "strict-origin-when-cross-origin",
"body": "{\"pauri\":[{\"line_number\":1,\"content_unicode\":\"ਆਪ ਅਛਤ ਸਮਰੱਥ ਪ੍ਰਭੁ ਦਈ ਬਡਾਈ ਨਾਮ ।\",\"content_gs\":\"Awp ACq smr`Q pRBu deI bfweI nwm [\",\"content_transliteration_english\":\"aap achhat samara'th prabh dhiee baddaiee naam |\",\"first_letters\":\"ਆਅਸਪਦਬਨ\",\"thamkis\":[],\"vishraams\":[]}],\"last_pauri_id\":60}",
"method": "POST",
"mode": "cors",
"credentials": "omit"
});
Hello beloved SO community.
I have a problem that tortures me for months with no solution.
I am trying to make a request at an HTTP/2 endpoint that uses some headers that start with a colon. Example:
:method: "POST"
I have tried with python(hyper, requests), php(guzzle) and js(fetch).
I have managed, presumably, with js to achieve the required result but the CORS policy returns me an "opaque" result.
Any help will be great!
JS result presumbaly correct "opaque"
fetch("https://www.example.com/users/sign_in",
{
"credentials":"include",
"headers":{
"accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"accept-language":"en-US,en;q=0.9,el;q=0.8",
"cache-control":"max-age=0",
"content-type":"application/x-www-form-urlencoded",
"accept-encoding": "gzip, deflate, br",
"content-length": 614,
"origin": "https://www.example.com",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "same-origin",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36",
},
"referrer":"https://www.example.com/users/sign_in",
"referrerPolicy":"no-referrer-when-downgrade",
"redirect": "follow",
"body":"..."
"method":"POST",
"mode":"no-cors",
":authority": "www.example.com",
":method": "POST",
":path": "/users/sign_in",
":scheme": "https"
})
Python result 500 or 404
context = tls.init_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
with HTTP20Connection('www.example.com', port=443, ssl_context=context) as c:
headers = {
":authority": "www.example.com",
":method": "GET",
":path": "/users/sign_in",
":scheme": "https",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"accept-encoding": "gzip, deflate, br",
"accept-language": "en-US,en;q=0.9,el;q=0.8",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "none",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
}
c.request('GET', 'www.example.com/users/sign_in', headers=headers)
PHP result 500 or curl error 55
$jar = new CookieJar;
$client = new Client([
// Base URI is used with relative requests
'cookies' => $jar,
'version' => 2.0,
'debug' => fopen('php://stderr', 'w'),
]);
$client->request('GET', 'https://www.example.com/users/sign_in');
$response = $client->request('POST', 'https://www.example.com/users/sign_in', [
'headers' => [
":authority"=> "www.example.com",
":method"=> "POST",
":path"=> "/users/sign_in",
":scheme"=> "https",
"accept"=> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"accept-encoding"=> "gzip, deflate, br",
"accept-language"=> "en-US,en;q=0.9,el;q=0.8",
"cache-control"=> "max-age=0",
"content-length"=> "616",
"content-type"=> "application/x-www-form-urlencoded",
"origin"=> "https://www.example.com",
"referer"=> "https://www.example.com/users/sign_in",
"sec-fetch-mode"=> "navigate",
"sec-fetch-site"=> "same-origin",
"sec-fetch-user"=> "?1",
"upgrade-insecure-requests"=> "1",
"user-agent"=> "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
],
'form_params' => [ ... ],
'version' => 2.0,
'allow_redirects' => true
]);
These are HTTP/2 pseudo-headers that apply to requests and responses within an HTTP/2 stream. HTTP/2 creates a single persistent connection from each distinct origin end-point to a server. That connection transmits multiple requests and responses to and from the end-point; these are parsed into "frames" and transmitted as "streams". HTTP/2 can interleave frames from multiple request and response streams simultaneously to get huge performance benefits. intro to http/2
Pseudo-headers apply to streams; a different set of headers apply to the connection itself. Four pseudo-headers are defined for requests: :method, :scheme, :authority, and :path. No others are allowed. These 4 must be included in every request header block and they must precede any other headers:
"All pseudo-header fields MUST appear in the header block before
regular header fields. Any request or response that contains a
pseudo-header field that appears in a header block after a regular
header field MUST be treated as malformed (Section 8.1.2.6)." http2 spec
I'm not familiar with how 'fetch' implements the headers, but in your code above you seem to have the pseudo-headers outside the header block, and they are placed at the end. Might be screwing up the fetch.
I make the following request with Axios:
axios.get("http://request.url/app.php", {
headers: {
"Accept": "application/json",
"X-Application-Key": "my-api-key",
},
params: {
url: "http://some/url",
format: "json",
param1: 1,
param2: 99999,
},
});
Heres the mock:
const myAPI = nock("http://request.url/");
myAPI
.get("/app.php")
.query(({url}) => url === "http://some/url")
.replyWithFile(200, path.resolve(__dirname, "my-response.json"), {
"Content-Type": "application/json",
});
Everything works fine as long as the X-Application-Key is not present in the request. When the X-Application-Key header is present then I get the following error from nock:
Error: Error: Nock: No match for request {
"method": "OPTIONS",
"url": "<request url goes here>",
"headers": {
"origin": "http://localhost",
"access-control-request-method": "GET",
"access-control-request-headers": "X-Application-Key",
"user-agent": "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0",
"host": "<my host goes here>",
"content-length": 0
}
}
I know it has something to do with the OPTIONS request, but I have no idea how to get around this issue.
I tried to use .matchHeader() methods in a following way:
myAPI
.get("/app.php")
.matchHeader("Accept", () => true)
.matchHeader("X-Mashape-Key", () => true)
.query(({url}) => url === "http://some/url")
.replyWithFile(200, path.resolve(__dirname, "my-response.json"), {
"Content-Type": "application/json",
});
But it doesn't change anything.
I found the solution. It has nothing to do with nock. It was an issue on the Axios end. It turned out that I have to use the axios/lib/adapters/http adapter when calling Axios in node environment.
So the solution is to initialize Axios this way:
import * as httpAdapter from "axios/lib/adapters/http";
const axios = Axios.create({
adapter: httpAdapter,
// Other options
});