Http Post Request from Angular doesn't work - javascript

I am sending a post request this way(the baseURL is correct, the path /api/backend/valuePairs exists on the server).
sendValues(valuepairList:{x:number;fx:number}[]): Observable<boolean> {
const headers = new Headers({'Content-Type': 'application/json'});
const options = new RequestOptions({headers: headers});
console.log("sending to server: ",JSON.stringify(valuepairList)); //this seems ok too
return this.http.post(this.baseUrl + '/api/backend/valuePairs', {'data': JSON.stringify(valuepairList)}, options)
.map(FunctionapproximationService.extractData)
.catch(FunctionapproximationService.handleError);
}
But looking in Chrome at the website in Inspect mode / Networks nothing is sent during the execution of this function.(It is executed, the logging inside the function appears). Does someone has idea about what I am doing wrong? Thank you.

Nothing is sent because observables are lazy by default. You need to subscribe to them in order to invoke the HTTP request.
sendValues(args).subscribe(result => console.log(result))
The function passed to subscribe function will be called when the response arrives. It also accepts other functions for error handling and one that is called when the stream is completed, but I leave that to you to figure out from the documentation.
In RxJS worl, .subscribe() is basically like calling a usual JS function with parans: (). To execute a function, you need to call it. To execute an observable, you need to subscribe to it.

Related

Overwriting an existing command with Cypress

I'm trying to overwrite an existing command in Cypress.io. I'm looking to log() a route response's status & the route's url to extend the functionality of the built-in route(). Unfortunately, I get this message The route undefined had a undefined status code. in the console. Note, I'm using the browser's console momentarily. Eventually, I'll use the log() built-in method. This is what I have tried so far:
cypress/support/commands.js
Cypress.Commands.overwrite('route', (originalFn, response) => {
console.log(`The route ${response.url} had a ${response.status} status code.`);
return originalFn(response);
});
Update:
I'm getting the route now, but I still don't get response or status. This is my current code:
Cypress.Commands.overwrite('route', (originalFn, url, response) => {
console.log(`The route ${url} had ${response} status code`);
return originalFn(url, response);
});
When using the pattern cy.route(method, url, response), the response parameter is use to stub the call and return the supplied response to your app, see (route() - Arguments)
response (String, Object, Array)
Supply a response body to stub in the matching route.
Note that creating an overwrite of cy.route() will be hooking into the route configuration, not the capture of the route.
The pattern cy.route(options) has an onResponse option which can be used to console.log() the response, but cy.log() does not work there, probably because we invoke a command inside a command.
Cypress.log() can be used instead.
cy.route({
url: 'http://example.com',
method: 'GET',
onResponse: (response => {
const message = `The route '${response.url}' had a ${response.status} status code.`;
const log = Cypress.log({
displayName: 'Route debugging',
message: message,
consoleProps: () => {
// return an object which will
// print to dev tools console on click
return {
message: message,
}
}
})
log.finish(); // remove log spinner
})
})
/*
Command log output:
ROUTE DEBUGGING
The route 'http://example.com' had a 200 status code.
*/
Depending on what you're trying to achieve, there are a couple of options. Richard's answer above describes one approach - I'll attempt to cover some others.
(Note: The Cypress documentation at https://docs.cypress.io/ probably will give you a better understanding than this answer. I'll try to link the relevant articles inline)
(You can skip ahead to the section on 'Inspecting Api Responses' if you don't care why your code isn't working)
What's happening in your code
Let's look at the example code from https://docs.cypress.io/api/commands/route.html#Examples
cy.server()
cy.route('**/users').as('getUsers')
cy.visit('/users')
cy.wait('#getUsers')
Without your overwrite, cy.route here just registers the route, so you can wait for it later (Remember, cy.route does not make any api calls itself). With your overwrite, cy.route is completely replaced with your callback:
Cypress.Commands.overwrite('route', (originalFn, url, response) => {
console.log(`The route ${url} had ${response} status code`);
return originalFn(url, response);
});
So when cy.route('**/users') is called, it will instead evaluate
(originalFn, url, response) => {
console.log(`The route ${url} had ${response} status code`); // Logs "The route **/users had undefined status code"
return originalFn(url, response); // Registers the route with an mock value of undefined
})(originalCypressRouteFn, '**/users')
You can see why response is undefined - it's not passed in to the route call at all, since the request hasn't even been made.
Note that if we were attempting to mock the call instead (See https://docs.cypress.io/api/commands/route.html#With-Stubbing)
cy.route('https://localhost:7777/surveys/customer?email=john#doe.com', [
{
id: 1,
name: 'john'
}
])
You would instead log
"The route https://localhost:7777/surveys/customer?email=john#doe.com had [object Object] status code"
Inspecting Api Responses
If you just want to inspect the response from an api, you can use the using the built-in debugging tools (after calling cypress open). The browser's Network tab is available (which will record all requests made during a given test run), and you can additionally click on the response recorded in the left panel, which will log the request and response to the browser console.
If you're attempting to assert on the response to an api call, you can use cy.wait (See https://docs.cypress.io/guides/guides/network-requests.html#Waiting) to get access to the underlying xhr request after it finishes:
cy.wait('#apiCheck').then((xhr) => {
assert.isNotNull(xhr.response.body.data, '1st API call has data')
})
If you want a record of the APIs calls made during a CLI run (using cypress run), you can:
Print debug info, which will give you a lot of information, including all requests and responses (See https://docs.cypress.io/guides/references/troubleshooting.html#Print-DEBUG-logs): DEBUG=cypress:* cypress run (You can change cypress:* to limit the scope of the debug to just api calls, though I don't know off the top of my head what the namespace you'll want is)
Use a plugin that records all requests (e.g. https://github.com/NeuraLegion/cypress-har-generator)

Invoking Rest API from Lambda (JS; Web Console)

_
MY CHALLENGE:
I would like to access a third party Rest API from within my Lambda function. (e.g."http://www.mocky.io/v2/5c62a4523000004a00019907").
This will provide back a JSON file which I will then use for data extraction
_
MY CURRENT CODE:
var http = require('http');
exports.handler = function(event, context, callback) {
console.log('start request to Mocky');
http.get('http://www.mocky.io/v2/5c62a4523000004a00019907', function(res) {
console.log(res);
})
.on('error', function(e) {
console.log("Got error: " + e.message);
});
};
This does not throw an error but also does not seem to provide back the JSON
_
MY OPEN QUESTIONS:
1) How can I extract the JSON so that I can work on it
2) I will probably need to also send through an Authentification in the request header (Bearer) in the future. Will this also be possible with this method?
The problem is likely that your lambda function is exiting before logging the response.
We use Authorization headers all the time to call our lambdas. The issue of if you can use one to call the third party API is up to them, not you, so check the documentation.
Since your HTTP call is executed asynchronously, the execution of the lambda continues while that call is being resolved. Since there are no more commands in the lambda, it exits before your response returns and can be logged.
EDIT: the http.get module is difficult to use cleanly with async/await. I usually use superagent, axios, or request for that reason, or even node-fetch. I'll use request in my answer. If you must use the native module, then see EG this answer. Otherwise, npm install request request-promise and use my answer below.
The scheme that many people use these days for this kind of call uses async/await, for example (Requires Node 8+):
var request = require('request-promise')
exports.handler = async function(event, context, callback) {
console.log('start request to Mocky');
try {
const res = await request.get('http://www.mocky.io/v2/5c62a4523000004a00019907')
console.log(res)
callback(null, { statusCode: 200, body: JSON.stringify(res) })
}
catch(err) {
console.error(err.message)
callback('Got error ' + err.message)
}
};
The async/await version is much easier to follow IMO.
Everything inside an async function that is marked with await with be resolved before the execution continues. There are lots of articles about this around, try this one.
There are a lot of guys having an equal problem already solved... Look at that
or that

How can I make a Cloudflare worker which overwrites a response status code but preserves the rest of the response?

Specifically I am interested in changing all responses with code 403 to code 404, and changing all responses with code 301 to 302. I do not want any other part of the response to change, except the status text (which I want to be empty). Below is my own attempt at this:
addEventListener("fetch", event => {
event.respondWith(fetchAndModify(event.request));
});
async function fetchAndModify(request) {
// Send the request on to the origin server.
const response = await fetch(request);
const body = await response.body
newStatus = response.status
if (response.status == 403) {
newStatus = 404
} else if (response.status == 301) {
newStatus = 302
}
// Return modified response.
return new Response(body, {
status: newStatus,
statusText: "",
headers: response.headers
});
}
I have confirmed that this code works. I would like to know if there is any possibility at all that this overwrites part of the response other than the status code or text, and if so, how can I avoid that? If this goes against certain best practices of Cloudflare workers or javascript, please describe which ones and why.
You've stumbled on a real problem with the Fetch API spec as it is written today.
As of now, status, statusText, and headers are the only standard properties of Response's init structure. However, there's no guarantee that they will remain the only properties forever, and no guarantee that an implementation doesn't provide additional non-standard or not-yet-standard properties.
In fact, Cloudflare Workers today implements a non-standard property: webSocket, which is used to implement WebSocket proxying. This property is present if the request passed to fetch() was a WebSocket initiation request and the origin server completed a WebSocket handshake. In this case, if you drop the webSocket field from the Response, WebSocket proxying will break -- which may or may not matter to you.
Unfortunately, the standard does not specify any good way to rewrite a single property of a Response without potentially dropping unanticipated properties. This differs from Request objects, which do offer a (somewhat awkward) way to do such rewrites: Request's constructor can take another Request object as the first parameter, in which case the second parameter specifies only the properties to modify. Alternately, to modify only the URL, you can pass the URL as the first parameter and a Request object as the second parameter. This works because a Request object happens to be the same "shape" as the constructor's initializer structure (it's unclear if the spec authors intended this or if it was a happy accident). Exmaples:
// change URL
request = new Request(newUrl, request);
// change method (or any other property)
request = new Request(request, {method: "GET"});
But for Response, you cannot pass an existing Response object as the first parameter to Response's constructor. There are straightforward ways to modify the body and headers:
// change response body
response = new Response(newBody, response);
// change response headers
// Making a copy of a Response object makes headers mutable.
response = new Response(response.body, response);
response.headers.set("Foo", "bar");
But if you want to modify status... well, there's a trick you can do, but it's not pretty:
// Create an initializer by copying the Response's enumerable fields
// into a new object.
let init = {...response};
// Modify it.
init.status = 404;
init.statusText = "Not Found";
// Work around a bug where `webSocket` is `null` but needs to be `undefined`.
// (Sorry, I only just noticed this when testing this answer! We'll fix this
// in the future.)
init.webSocket = init.webSocket || undefined;
// Create a new Response.
response = new Response(response.body, init);
But, ugh, that sure was ugly.
I have proposed improvements to the Fetch API to solve this, but I haven't yet had time to follow through on them. :(

Unit test for a sub-method which called from main method and include http-request authoraztion

I faced to a really complicated scenario, hope you guys give me a hint.
So I have a main method, which is a api endpoint, this method call another method to check if the user is authorized to use this endpoint or not.
The sub-endpoint which I called it apiAuthorazation send a get request to a thirdparty url, and this third-party return a response which says this user is authorized, or not!
So I already have a unit test for the main method, but now I want add this authorization part to it. I know I can use muck libs like Nock or other similar libraries, but my problem is how can I add this sub-method to my uit test.
This is my api endpoint method :
module.exports.api = (event, context, callback) => {
// Authorization
let getBearertoken = event.headers.Authorization.replace("Bearer ", '');
let isAuhtorized = utilities.apiAuthorazation(getBearertoken);
//Some other Codes
}
As you can see I passed a bearer token to my sub-method, and apiAuthorazation method will going to send this token to a third-party api, and the method is like this :
module.exports.apiAuthorazation = function (token){
let url = process.env.authApiUrl
requestLib(`${url}/${token}`, function (error, response, body) {
if (error) console.log('Error while checking token :', error);
if(response.isValidUser){
return true;
}
else{
return false;
}
});
}
Now my question is how can I include this sub-method to my main method unit test. I use mocha and chai for unit testing, bceause the berear token will expire soon, so when I run the test, I send a sample event which have the berear token in it, but it's already expired, so its kind of useless.
When you unit test Api, you can mock apiAuthorization for the two scenarios (true or false) and test if Api behaves as expected. Dont worry about what happens inside the sub method at all for the Api tests as you are testing Api here and the focus is not on what is happening inside the sub method, apiAuthorization.

node.js and hapi: fetching data from a database synchronously

Coming from a .net world where synchronicity is a given I can query my data from a back end source such as a database, lucene, or even another API, I'm having a trouble finding a good sample of this for node.js where async is the norm.
The issue I'm having is that a client is making an API call to my hapi server, and from there I need to take in the parameters and form an Elasticsearch query to call, using the request library, and then wait for the instance to return before populating my view and sending it back to the client, problem being is that the request library uses a callback once the data is returned, and the empty view has long been returned to the client by then.
Attempting to place the return within the call back doesn't work since the EOF for the javascript was already hit and null returned in it's place, what is the best way to retrieve data within a service call?
EX:
var request = require('request');
var options = {
url: 'localhost:9200',
path: {params},
body: {
{params}
}
}
request.get(options, function(error, response){
// do data manipulation and set view data
}
// generate the view and return the view to be sent back to client
Wrap request call in your hapi handler by nesting callbacks so that the async tasks execute in the correct logic order. Pseudo hapi handler code is as following
function (request, reply) {
Elasticsearch.query((err, results) => {
if (err) {
return reply('Error occurred getting info from Elasticsearch')
}
//data is available for view
});
}
As I said earlier in your last question, use hapi's pre handlers to help you do async tasks before replying to your client. See docs here for more info. Also use wreck instead of request it is more robust and simpler to use

Categories