request-promise not recognizing the URI when it is stated in the option object - http

I have a method that should return a response from another server. I use request-promise and put the URL in the options object.
As you can see in the code below, all is in good shape, but when I send the request, it returns 404 - resource not found.
When I change the request(options) method with request("https://api.quickpay.net/payments"), I get a positive answer from the server -- it tells me to add headers and so forth, which is positive.
public requestNewQuickpayPayment(order_id: String, currency : String, callback: Function) {
var options = {
method: 'POST',
uri: 'https://api.quickpay.net/payments',
form:{
order_id : "order123",
currency : "dkk"
},
headers: {
"Content-Type" : "application/json",
'Accept-Version': 'v10'
},
json: true
};
request(options).then((response:any)=>{
console.log(response);
return response;
}).catch((error:any)=>{
console.log(error);
return error;
}).finally(()=>{
console.log("done");
})
}
Something from the console
Request {
_events: [Object],
_eventsCount: 5,
_maxListeners: undefined,
method: 'POST',
uri: [Url],
transform2xxOnly: true,
headers: [Object],
readable: true,
writable: true,
explicitMethod: true,
_qs: [Querystring],
_auth: [Auth],
_oauth: [OAuth],
_multipart: [Multipart],
_redirect: [Redirect],
_tunnel: [Tunnel],
_rp_resolve: [Function],
_rp_reject: [Function],
_rp_promise: [Promise],
_rp_callbackOrig: undefined,
callback: [Function],
_rp_options: [Object],
setHeader: [Function],
hasHeader: [Function],
getHeader: [Function],
removeHeader: [Function],
localAddress: undefined,
pool: {},
dests: [],
__isRequestRequest: true,
_callback: [Function: RP$callback],
proxy: null,
tunnel: true,
setHost: true,
originalCookieHeader: undefined,
_disableCookies: true,
_jar: undefined,
port: 443,
host: 'api.quickpay.net',
body: 'order_id=asdasdasd&currency=dkk',
path: '/payments',
_json: true,
httpModule: [Object],
agentClass: [Function],
agent: [Agent],
_started: true,
href: 'https://api.quickpay.net/payments',
req: [ClientRequest],
ntick: true,
response: [Circular],
originalHost: 'api.quickpay.net',
originalHostHeaderName: 'host',
responseContent: [Circular],
_destdata: true,
_ended: true,
_callbackCalled: true },
toJSON: [Function: responseToJSON],
caseless: Caseless { dict: [Object] },
body: '404 Not Found' } }
What is wrong here? The path to the ressource is checked many times - nothing is wrong there....

For api.quickpay.net, 404 Not Found does not mean the URI is not recognized, but indicating invalid request body. It has nothing to do with whether the URI is stated in options object, or stated as string parameter of request().
Here is a simple experiment. The code below would return "positive" result, warning missing headers ({"error":"Accept-Version http header is required"}), which indicates that the URI is "recognized":
request({
method: 'POST',
uri: 'https://api.quickpay.net/payments'
}, function(err, res, body) {
console.log(body);
});
However, after the missing Accept-Version header is added, we get 404 Not Found:
request({
method: 'POST',
uri: 'https://api.quickpay.net/payments',
headers: {
'Accept-Version': 'v10'
}
}, function(err, res, body) {
console.log(body);
});
Thus, in order to make the API call work, you need to make the HTTP request valid (following to the document).

Related

AxiosError: connect ECONNREFUSED 127.0.0.1:3000

First question I'm asking, hoping for a "miracle", safe to say I'm a Jr Developer:
I have a NextJs project and I am using Prisma & Supabase. I made it very simple, I only have one item in the database, one index.js page with a getserversideprops function. When I use axios to get from the API folder, this works locally, but when I deploy it it doesn't work, this is the log on Vercel when I deploy:
[GET] /
22:01:04:79
d: false,
finished: false,
destroyed: false,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: true,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
afterWriteTickInfo: null,
buffered: [],
bufferedIndex: 0,
allBuffers: true,
allNoop: true,
pendingcb: 0,
constructed: true,
prefinished: false,
errorEmitted: false,
emitClose: true,
autoDestroy: true,
errored: null,
closed: false,
closeEmitted: false,
[Symbol(kOnFinished)]: []
},
_events: [Object: null prototype] {
response: [Function: handleResponse],
error: [Function: handleRequestError],
socket: [Function: handleRequestSocket]
},
_eventsCount: 3,
_maxListeners: undefined,
_options: {
maxRedirects: 21,
maxBodyLength: Infinity,
protocol: 'http:',
path: '/api/fetches/get-products',
method: 'GET',
headers: [Object: null prototype],
agents: [Object],
auth: undefined,
beforeRedirect: [Function: dispatchBeforeRedirect],
beforeRedirects: [Object],
hostname: 'localhost',
port: '3000',
agent: undefined,
nativeProtocols: [Object],
pathname: '/api/fetches/get-products'
},
_ended: true,
_ending: true,
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 0,
_requestBodyBuffers: [],
_onNativeResponse: [Function (anonymous)],
_currentRequest: ClientRequest {
_events: [Object: null prototype],
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
socket: [Socket],
_header: 'GET /api/fetches/get-products HTTP/1.1\r\n' +
'Accept: application/json, text/plain, /\r\n' +
'User-Agent: axios/1.3.0\r\n' +
'Accept-Encoding: gzip, compress, deflate, br\r\n' +
'Host: localhost:3000\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: [Agent],
socketPath: undefined,
method: 'GET',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/api/fetches/get-products',
_ended: false,
res: null,
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'localhost',
protocol: 'http:',
_redirectable: [Circular *1],
[Symbol(kCapture)]: false,
[Symbol(kBytesWritten)]: 0,
[Symbol(kEndCalled)]: true,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype],
[Symbol(kUniqueHeaders)]: null
},
_currentUrl: 'http://localhost:3000/api/fetches/get-products',
[Symbol(kCapture)]: false
},
cause: Error: connect ECONNREFUSED 127.0.0.1:3000
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1300:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 3000
},
page: '/'
}
RequestId: 91b310f3-2890-4aa3-b936-1cea9a199692 Error: Runtime exited with error: exit status 1
Runtime.ExitError
this is my index.js
export default function Home({products}) {
return (
<>
<main>
{JSON.stringify(products)}
</main>
</>
)
}
export async function getServerSideProps() {
const port = process.env.API_HOST_PORT || 3000
const host = `http://localhost:${port}`
const { data: products } = await axios.get(`${host}/api/fetches/get-products`);
return { props: { products } };
}
the .env files are imported at the top.. You will need to let me know what other information you need from my end so I can inform you.
It's hard for me to debug because it doesn't make sense on my end, I've tried deploying with Vercel and Digital Ocean, but both have a 500 error and when I check the logs it says what I shared. Schema was built correctly, the API Keys are correct. I actually "copied" this from a different project so I could practice more with prisma, but this one doesn't work..

Supabase JS reponse no data property

I tried to configure a next js project with supabase
But the data I receive is not consistent
To do this I have configured the following 3 files :
.env.local
NEXT_PUBLIC_SUPABASE_URL= ********
NEXT_PUBLIC_SUPABASE_ANON_KEY= ********
supabase.js
import { createClient } from '#supabase/supabase-js'
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
)
export default supabase;
pages/api/posts.js
import supabase from '../../utils/supabase';
export default function handler(req, res) {
const posts = supabase.from("posts").select("*");
res.status(200).json(posts);
}
When I console log my posts variable, I have no data property.
It returned this,
PostgrestFilterBuilder {
fetch: [Function (anonymous)],
shouldThrowOnError: false,
allowEmpty: false,
url: URL {
href: '********/rest/v1/posts?select=*',
origin: '********',
protocol: 'https:',
username: '',
password: '',
host: '********',
hostname: '********',
port: '',
pathname: '/rest/v1/posts',
search: '?select=*',
searchParams: URLSearchParams { 'select' => '*' },
hash: ''
},
headers: {
'X-Client-Info': 'supabase-js/1.35.4',
apikey: '********',
Authorization: 'Bearer ********'
},
schema: 'public',
_subscription: null,
_realtime: RealtimeClient {
accessToken: null,
channels: [],
endPoint: 'wss://********/realtime/v1/websocket',
headers: { 'X-Client-Info': 'supabase-js/1.35.4' },
params: {
apikey: '********'
},
timeout: 10000,
transport: [Function: W3CWebSocket],
heartbeatIntervalMs: 30000,
longpollerTimeout: 20000,
heartbeatTimer: undefined,
pendingHeartbeatRef: null,
ref: 0,
logger: [Function: noop],
conn: null,
sendBuffer: [],
serializer: Serializer { HEADER_LENGTH: 1 },
stateChangeCallbacks: { open: [], close: [], error: [], message: [] },
reconnectAfterMs: [Function (anonymous)],
encode: [Function (anonymous)],
decode: [Function: bound decode],
reconnectTimer: Timer {
callback: [Function (anonymous)],
timerCalc: [Function (anonymous)],
timer: undefined,
tries: 0
}
},
_headers: {
'X-Client-Info': 'supabase-js/1.35.4',
apikey: '********',
Authorization: 'Bearer ********'
},
_schema: 'public',
_table: 'posts',
method: 'GET',
cs: [Function: contains],
cd: [Function: containedBy],
sl: [Function: rangeLt],
sr: [Function: rangeGt],
nxl: [Function: rangeGte],
nxr: [Function: rangeLte],
adj: [Function: rangeAdjacent],
ov: [Function: overlaps]
}
Also when I look at the dashboard of my supabase database I see that no query is receive
It seems that this query is not sent to the supabase API but I have no idea why ?
You need to await the Promise: https://supabase.com/docs/reference/javascript/select
import supabase from '../../utils/supabase';
export default async function handler(req, res) {
const posts = await supabase.from("posts").select("*");
res.status(200).json(posts);
}

NextJS Redirect query parameter to path

I want to redirect my url from /shop?q=blabla to /shop/blabla.
My next.config.js file:
{
source: '/shop?q=:sef',
destination: '/shop/:sef',
permanent: true,
},
doesn't work. And returns error "Reason: Unexpected MODIFIER at 7, expected END"
I also tried code below;
{
source: '/shop',
has: [
{
type: 'query',
key: 'q',
value: '(?<paramName>.*)'
},
],
permanent: true,
destination: '/shop/:paramName',
},
and It doesnt work with no errors.

403 status from Firebase Cloud Function -> Google Books API

I'm currently working on creating a Firebase Cloud Function that retrieve a list of books from the NYTimes API and grabs some additional information from the Google Books API. By using the following URL : "https://www.googleapis.com/books/v1/volumes?q=isbn:&key=" I'm able to retrieve books' details based on an ISBN.
My FREE quota for Google Books API is 1000 request per day and 100 request every 100 seconds per user. I'm only sending 15 requests and my current quota is below 200.
My key is restricted only to be used with Google Books API and it could be use from anywhere (iOS, web, android...etc)
After building the function I'm testing everything locally and data gets populated correctly although once I deploy the function on firebase I get a 403 status code when trying to access to the API.
Unfortunately I'm not getting more details about the error. It just this:
{ Error: Request failed with status code 403
at createError (/user_code/node_modules/axios/lib/core/createError.js:16:15)
at settle (/user_code/node_modules/axios/lib/core/settle.js:18:12)
at IncomingMessage.handleStreamEnd (/user_code/node_modules/axios/lib/adapters/http.js:201:11)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
config:
{ adapter: [Function: httpAdapter],
transformRequest: { '0': [Function: transformRequest] },
transformResponse: { '0': [Function: transformResponse] },
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers:
{ Accept: 'application/json, text/plain, */*',
'User-Agent': 'axios/0.18.0' },
method: 'get',
url: 'https://www.googleapis.com/books/v1/volumes?q=isbn:0525520384&key=##########’,
data: undefined },
request:
ClientRequest {
domain: null,
_events:
{ socket: [Function],
abort: [Function],
aborted: [Function],
error: [Function],
timeout: [Function],
prefinish: [Function: requestOnPrefinish] },
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
upgrading: false,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedHeader: {},
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: null,
npnProtocol: false,
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 10,
connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: 'www.googleapis.com',
_readableState: [Object],
readable: false,
domain: null,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
destroyed: true,
_bytesDispatched: 210,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular],
read: [Function],
_consuming: true,
write: [Function: writeAfterFIN],
_idleNext: null,
_idlePrev: null,
_idleTimeout: -1 },
connection:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: null,
npnProtocol: false,
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 10,
connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: 'www.googleapis.com',
_readableState: [Object],
readable: false,
domain: null,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
destroyed: true,
_bytesDispatched: 210,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular],
read: [Function],
_consuming: true,
write: [Function: writeAfterFIN],
_idleNext: null,
_idlePrev: null,
_idleTimeout: -1 },
_header: 'GET /books/v1/volumes?q=isbn:0525520384&key=##### HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nUser-Agent: axios/0.18.0\r\nHost: www.googleapis.com\r\nConnection: close\r\n\r\n',
_headers:
{ accept: 'application/json, text/plain, */*',
'user-agent': 'axios/0.18.0',
host: 'www.googleapis.com' },
_headerNames: { accept: 'Accept', 'user-agent': 'User-Agent', host: 'Host' },
_onPendingData: null,
agent:
Agent {
domai
I was facing a similar issue. I was able to sucessfully use the Books API when I was running my functions locally (ie. firebase serve). But when I deployed the functions and the app to hosting, I was getting a mysterious 403: Forbidden error.
I tried several things so I'm not sure which helped so I'll just list everything:
Updated firebase functions: npm install --save firebase-functions#latest
Switched from using node-fetch to using axios for calling the API
Add country to URL: https://www.googleapis.com/books/v1/volumes?country=US&q=insubject:${randomWord}&key=${functions.config().books.api.key}
Regenerated Google Books API key
Removed all Application restrictions in the google cloud console
Hope this helps somebody out there because I was wrestling with it for hours!
By adding more restriction to the key (HTTP Only) and adding a referer header to my request and finally adding a country code to the end of the request my original issue is now gone.
Note: Referer should match the http restriction value on your key.
Final URL :
https://www.googleapis.com/books/v1/volumes?q=isbn:#book-isbn#&key=#app-key#&country=US
Google books apis need to know the country to show relevant books. either pass it through the country parameter or you can use the client to call the api's directly.

Debugging Sinon.js in some smart way

We're using Sinon.JS for some integration-ish testing and I'm having a problem I need to debug somehow. We're using the fakeServer.create() method like so:
server = Sinon.fakeServer.create()
server.autoRespond = true
server.respondWith "GET", ...
Normally when working with xhr, you just open the network-tab in chrome dev tools and you can see all calls to the server, the order of them and the responses from the server. This is super helpful for debugging. Can I achieve something similar when working with Sinon?
If you are using karma-runner in a browser such as Google Chrome, you can use the "debug" feature. The general idea is starting the karma test with runonce disabled, and then clicking the debug button on the browser window that pops up. You can set breakpoints and debug the tests in a web browser like you normally would, including opening up the network tab in chrome.
The documentation in this area is a little sparse, but one of the configuration options for Sinon's createFakeServer() is logger, here's an example of how you might use it:
var server = sinon.createFakeServer({ logger: console.log });
This will produce:
Request:
[FakeXMLHttpRequest] {
async: true,
errorFlag: false,
eventListeners: {
abort: [function () {}],
error: [function () {}],
load: [function () {}],
loadend: [function () {}],
loadstart: [function () {}],
progress: [function () {}],
timeout: [function () {}]
},
logError: function logError() {},
method: "GET",
onSend: function () {},
onerror: function () {},
onload: function () {},
onreadystatechange: function () {},
password: undefined,
readyState: 1,
requestBody: null,
requestHeaders: {
Accept: "application/json, text/javascript, */*; q=0.01",
Content-Type: "text/plain;charset=utf-8",
X-Requested-With: "XMLHttpRequest",
twProjectsVer: "2.0"
},
response: (empty string),
responseText: (empty string),
responseType: (empty string),
responseXML: null,
sendFlag: true,
status: 0,
statusText: (empty string),
timeout: 0,
unsafeHeadersEnabled: function () {},
upload: {
eventListeners: {
abort: [function () {}],
error: [function () {}],
load: [function () {}],
loadend: [function () {}],
loadstart: [function () {}],
progress: [function () {}],
timeout: [function () {}]
}
},
url: "/entities.json?page=1&pageSize=50&offsetCount=0",
username: undefined,
withCredentials: false
}
Response:
[404, { }, (empty string)]
Adding some more details to #dustinroepsch answer.
Start Karma with these options
karma start karma.conf.js --browsers=Chrome --single-run=false --debug
This will open up a Google Chrome instance that does not get closed once test completes. You should be able to view both the source and test files in Developer Tools -> Source. You can then place breakpoints and reload the page to debug.

Resources