Which method for doing http calls should i use: The documenations isn’t clear what are the differences pros/cons of each method
Method 1 (as per interactive docs Lesson 2 Step 9)
using import { Http, Headers, Response } from "#angular/http";
and
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
in to the app.module
similar to how its done in normal angular
Method 2: (https://docs.nativescript.org/cookbook/http)
const httpModule = require("http");
and using methods such as
httpModule.getString("https://httpbin.org/get") ...
Method 3 (https://docs.nativescript.org/tutorial/chapter-4)
var fetchModule = require("fetch");
and using methods such as
fetchModule.fetch(config.apiUrl + "user/" + config.appKey + "/login", { method: "POST", body: JSON.stringify({ username: viewModel.get("email"), password: viewModel.get("password") }), headers: getCommonHeaders() })
The first method is using Angular http service
Just like any service,it can be injected. Under the hood it calls lower level http calls such as fetch
The second method is using internal library called http. Not angular's.
Third one is a lower level,promise based ,pure native impelemnation for http calls api.
It all depends on what fw you use
Related
I am building an application using the Twitter API and Netlify (aws lambda functions)
This API requires these steps:
When the user goes to my /auth function, a link to the Twitter authentication is created
Once the user clicks that link, he is redirected to Twitter where a pop-up asks to allow my app to connect.
Once the user approves, he is redirected to my /auth function again but this time the authCode is set to a number rather than being undefined. This authCode is used to instantiate the twitter client class and authorize it.
A new instance of the Twitter client is created and authorized. This instance allows to query the tweets
1, 2 and 3 works. However, the authorized instance only lives inside the /auth function. How can I pass it to different functions without losing its instantiation?
How can I pass this instance to different server-less functions?
client = new Client(OAuthClient) this is what I want to pass around.
I tried with a Middleware with little success. It seems the twitter client class gets re-instantiated (so without authorization) for every server-less function
https://playful-salmiakki-67d50e.netlify.app/.netlify/functions/auth
import Client from 'twitter-api-sdk';
let client: Client;
const auth = async (event, context, callback) => {
const authCode = event.queryStringParameters ? event.queryStringParameters.code : undefined;
const authUrl = OAuthClient.generateAuthURL({
state: 'STATE',
code_challenge: 'challenge',
});
console.log('HERE LINK:');
console.log(authUrl);
if (authCode) {
await OAuthClient.requestAccessToken(authCode as string);
client = new Client(OAuthClient); <-- THIS IS WHAT I WANT TO PASS TO DIFFERENT FUNCTIONS
}
return {
statusCode: 200,
body: JSON.stringify({ message: 'Auth, go to the url displayed terminal'}),
myClient: client
};
};
exports.handler = middy().use(myMiddleware()).handler(auth);
I have a BFF needs to send some requests to ServiceA.
ServiceA is providing some API (GET, POST, ...) that we can deal with.
For example:
#Get('greeting')
getGreetingMessage(#Param('name') name: string): string {
return `Hello ${name}`;
}
In MicroService Architecture in NestJs I see the best practice in BFF to send requests to other servcies is to use Message patterns like cmd with payloads.
For example
constructor(
#Inject('SERVICE_A') private readonly clientServiceA: ClientProxy,
) {}
getGreetingFromServiceA() {
const startTs = Date.now();
const pattern = { cmd: 'greeting' };
const payload = {};
return this.clientServiceA
.send<string>(pattern, payload)
.pipe(
map((message: string) => ({ message, duration: Date.now() - startTs })),
);
}
So to do that I have to support MessagePattern in ServiceA like:
#MessagePattern({cmd: 'greeting'})
getGreetingMessage(name: string): string {
return `Hello ${name}`;
}
So my question is Is there a way to append MessagePattern to exisiting APIs in ServiceA? so I can call them with 2 different ways either by Rest GET Request or MessagePattern from BFF.
I'm thinking about using 2 docerators (Get and MessagePattern)
Like that
#Get('greeting')
#MessagePattern({cmd: 'greeting'})
getGreetingMessage(#Param('name') name: string): string {
return `Hello ${name}`;
}
If no, so how can I use a proxyClient to make http requests to other microservice in the BFF?
Actually it is not possible in NestJS to define more than one decorator to the same method in the controller but we make it a hybrid application which supports different communication protocols so we can call it via TCP or HTTP and so on like in this example https://docs.nestjs.com/faq/hybrid-application
I'm intercepting an API using cy.intercept(), and it appears that this API is being called two times so it gets intercepted two times, with different responses. I want to access the last intercepted one only. how can I do that?
cy.intercept({
url: `${Cypress.config().apiUrl}/ticket`,
method: 'GET',
}).as('assignedTicketAPI')
There was a recent question here How to match intercept on response, which is about tackling multiple requests on the same intercept.
You can wait twice on the same intercept alias, provided the route matching parameters are the same.
cy.wait('#assignedTicketAPI')
cy.wait('#assignedTicketAPI').then(interception => {...
It's also possible to count requests in the intercept and assign a unique alias to the 2nd one caught - Aliasing individual requests
let intercepted = 0
cy.intercept({
url: `${Cypress.config().apiUrl}/ticket`,
method: 'GET',
}, (req) => {
intercepted = intercepted + 1
if (intercepted === 2) {
req.alias = 'assignedTicketAPI2'
}
})
cy.wait('#assignedTicketAPI2').then(interception => {...
Apollo is not storing the header from the query dynamically.
pages/index.vue
methods: {
fetchCars() {
const token = Cookies.get('XSRF-TOKEN')
console.log(token) // 🟢 Token is shown in console
this.$apollo.query({
query: gql`
query {
cars {
uuid
name
}
}
`,
headers: {
'X-XSRF-TOKEN': token, // ⭕ Fetch without header
},
})
},
},
Is there a way to set the header value new for every Apollo request?
I have a separate Frontend and Backend. For the Frontend I am using Nuxt.js with Apollo. I want to have a session based communication with my server. For this reason I need to send the CSRF-Token with every Request.
Now the problem: On the first load of the page there is no Cookie set on the browser. I do a GET-Request on every initialization of my Nuxt application.
plugins/csrf.js
fetch('http://127.0.0.1:8000/api/csrf-cookie', {
credentials: 'include',
})
Now I have a valid Cookie set on my side and want to communicate with the GraphQL Server but my header is not set dynamically in the query. Does anyone know how I can solve this?
My Laravel Backend is throwing now a 419 Token Mismatch Exception because I did not send a CSRF-Token with my request.
Link to the repository: https://github.com/SuddenlyRust/session-based-auth
[SOLVED] Working solution: https://github.com/SuddenlyRust/session-based-auth/commit/de8fb9c18b00e58655f154f8d0c95a677d9b685b Thanks to the help of kofh in the Nuxt Apollo discord channel 🎉
In order to accomplish this, we need to access the code that gets run every time a fetch happens. This code lives inside your Apollo client's HttpLink. While the #nuxtjs/apollo module gives us many options, we can't quite configure this at such a high level.
Step 1: Creating a client plugin
As noted in the setup section of the Apollo module's docs, we can supply a path to a plugin that will define a clientConfig:
// nuxt.config.js
{
apollo: {
clientConfigs: {
default: '~/plugins/apollo-client.js'
}
}
}
This plugin should export a function which receives the nuxt context. It should return the configuration to be passed to the vue-cli-plugin-apollo's createApolloClient utility. You don't need to worry about that file, but it is how #nuxtjs/apollo creates the client internally.
Step 2: Creating the custom httpLink
In createApolloClient's options, we see we can disable defaultHttpLink and instead supply our own link. link needs to be the output of Apollo's official createHttpLink utility, docs for which can be found here. The option we're most interested in is the fetch option which as the docs state, is
a fetch compatible API for making a request
This boils down to meaning a function that takes uri and options parameters and returns a Promise that represents the network interaction.
Step 3: Creating the custom fetch method
As stated above, we need a function that takes uri and options and returns a promise. This function will be a simple passthrough to the standard fetch method (you may need to add isomorphic-fetch to your dependencies and import it here depending on your setup).
We'll extract your cookie the same as you did in your question, and then set it as a header. The fetch function should look like this:
(uri, options) => {
const token = Cookies.get('XSRF-TOKEN')
options.headers['X-XSRF-TOKEN'] = token
return fetch(uri, options)
}
Putting it all together
Ultimately, your ~/plugins/apollo-client.js file should look something like this:
import { createHttpLink } from 'apollo-link-http'
import fetch from 'isomorphic-fetch'
export default function(context) {
return {
defaultHttpLink: false,
link: createHttpLink({
uri: '/graphql',
credentials: 'include',
fetch: (uri, options) => {
const token = Cookies.get('XSRF-TOKEN')
options.headers['X-XSRF-TOKEN'] = token
return fetch(uri, options)
}
})
}
}
I am trying to get a response from a web service, specifically to add two WFS layers from geoserver to a leaflet web map. The first layer gets added no problem every time, but most of the time, the second layer fails, complaining that the callback function is not defined:
ReferenceError: getJson is not defined
But what is very strange to me is that the second layer will be added, only sometimes. Refreshing the page and trying again will almost always fail.
This is the code making the ajax call:
$(document).ready(function() {
...
$("#add-network-button").on("click", function() {setLocation("Moscow")})
function setLocation(locationName) {
var networkParameters = {
service: 'WFS',
version: '1.0.0',
request: 'GetFeature',
typeName: 'netex:' + locationData[locationName].networkWFSName,
maxFeatures: 99999,
outputFormat: 'text/javascript',
format_options: 'callback: getJson'
};
addWebService(map, WFSURL, networkParameters)
var buildingParameters = {
service: 'WFS',
version: '1.0.0',
request: 'GetFeature',
typeName: 'netex:' + locationData[locationName].buildingWFSName,
maxFeatures: 99999,
outputFormat: 'text/javascript',
format_options: 'callback: getJson'
};
addWebService(map, WFSURL, buildingParameters)
}
And here is the addWebService function:
var addWebService = function(map, WFSURL, WFSParameters) {
var leafletWFSParameters = L.Util.extend(WFSParameters);
console.log(WFSURL + L.Util.getParamString(leafletWFSParameters));
$.ajax({
url: WFSURL + L.Util.getParamString(leafletWFSParameters),
dataType: 'jsonp',
jsonpCallback: 'getJson',
success: handleJson,
cache: false
});
// TODO: add style
function handleJson(data) {
L.geoJson(data, {}).addTo(map);
}
}
You're using jsonp, which means the data you're getting back is not JSON, but javascript code that makes a call to a globally-defined function (which name is defined by jsonpCallback).
jQuery automagically creates a function with that name, performs the network request, and when that function runs, it destroys its own reference from the global scope.
You're performing two calls to addWebService() in quick succession, which trigger two jQuery $.ajax({jsonpCallback: 'getJson'}) calls. The second call is overwriting the globally-defined getJson callback function. When the first jsonp payload is received by your browser, the globally-defined getJson callback is destroyed. When the second jsonp payload is received, it tries to call a globally-defined getJson function, and failing. A classic race condition.
Let me quote jQuery's documentation for the jsonpCallback parameter on $.ajax(), empasis mine:
jsonpCallback
Type: String or Function()
Specify the callback function name for a JSONP request.
This value will be used instead of the random name
automatically generated by jQuery. It is preferable to let
jQuery generate a unique name as it'll make it easier to manage the
requests and provide callbacks and error handling. You may want to
specify the callback when you want to enable better browser caching of
GET requests.
I suggest you either use other transport format than JSONP, or use different callback names for each request.