I have a webapp made with Next.js and Apollo as show in example with-apollo. I want to serve multiple domains with my webapp (name-based virtual hosting). Unfortunately HttpLink of ApolloClient requires absolute server URL with domain but this makes backend app unable to recognize domain which user really visited. Is there a way to configure HttpLink with a dynamic URL based on real request or use relative URL or anything else?
Either use an Apollo Link to intercept the query and set uri property on the context
const authMiddleware = setContext((operation, { uri }) => {
return refreshToken().then(res => ({
uri: this.getURI()
})
}))
Or intercept the request with Angular's HttpClient interceptor and change the endpoint.
https://github.com/apollographql/apollo-angular/tree/master/packages/apollo-angular-link-http#options
Source: Updating uri of apollo client instance
The NextPageContext object passed to getInitialProps includes the req object when called on the server-side. So you can do something like:
WithApollo.getInitialProps = async ctx => {
const { AppTree, req } = ctx
const linkBaseUrl = req ? req.protocol + '://' + req.get('host') : ''
...
}
You can then pass this base url down to createApolloClient along with the initial state and prepend your HttpLink's url with it. On the client side, this will prepend an empty string (you only need the full URL on the server).
Related
I have a SSR Nuxt app. There is a middleware in the page code.
I dont know is I can use js-cookies library in that middleware and if it will work as I expected. I need to get and set up the cookie in browser and also get the cookie value on the server. All this steps in the middleware.
I mean
check if cookie is set via Cookies.get(key)
if not then set up the cookie via Cookies.set(key, value)
redirect to the server where I want to get this cookie value
Code should look like
async middleware(context) {
const token = context.route.query.token;
if (!token) {
const cookieToken = Cookies.get('cookieToken');
if( !cookieToken ) {
Cookies.set('cookieTokne', nanoId());
}
const result = await context.$api.campaignNewShare.createNewShare();
context.redirect({'name': 'campaigns-new', 'query': {token: result.data.token}});
}
},
Am I able to get cookie after the set on the server and can I get it in the browser after the redirect? I need to ensure both set and get in this middleware at once.
Use nuxt universal cookies and register on your modules, this way you can access the module everywhere on your nuxt app.
Using your code as example:
async middleware(context) {
const token = context.route.query.token;
if (!token) {
const cookieToken = context.$cookies.get('cookieToken');
if( !cookieToken ) {
context.$cookies.set('cookieToken', nanoId());
}
const result = await context.$api.campaignNewShare.createNewShare();
context.redirect({'name': 'campaigns-new', 'query': {token: result.data.token}});
}
},
I want to read the request cookie during a test written with the puppeteer. But I noticed that most of the requests I inspect have only referrer and user-agent headers. If I look at the same requests in Chrome dev tools, they have a lot more headers, including Cookie. To check it out, copy-paste the code below into https://try-puppeteer.appspot.com/.
const browser = await puppeteer.launch();
const page = await browser.newPage();
page.on('request', function(request) {
console.log(JSON.stringify(request.headers, null, 2));
});
await page.goto('https://google.com/', {waitUntil: 'networkidle'});
await browser.close();
Is there a restriction which request headers you can and can not access? Is it a limitation of Chrome itself or puppeteer?
Thanks for suggestions!
I also saw this when I was trying to use Puppeteer to test some CORS behaviour - I found the Origin header was missing from some requests.
Having a look around the GitHub issues I found an issue which mentioned Puppeteer does not listen to the Network.responseReceivedExtraInfo event of the underlying Chrome DevTools Protocol, this event provides extra response headers not available to the Network.responseReceived event. There is also a similar Network.requestWillBeSentExtraInfo event for requests.
Hooking up to these events seemed to get me all the headers I needed. Here is some sample code which captures the data from all these events and merges it onto a single object keyed by request ID:
// Setup.
const browser = await puppeteer.launch()
const page = await browser.newPage()
const cdpRequestDataRaw = await setupLoggingOfAllNetworkData(page)
// Make requests.
await page.goto('http://google.com/')
// Log captured request data.
console.log(JSON.stringify(cdpRequestDataRaw, null, 2))
await browser.close()
// Returns map of request ID to raw CDP request data. This will be populated as requests are made.
async function setupLoggingOfAllNetworkData(page) {
const cdpSession = await page.target().createCDPSession()
await cdpSession.send('Network.enable')
const cdpRequestDataRaw = {}
const addCDPRequestDataListener = (eventName) => {
cdpSession.on(eventName, request => {
cdpRequestDataRaw[request.requestId] = cdpRequestDataRaw[request.requestId] || {}
Object.assign(cdpRequestDataRaw[request.requestId], { [eventName]: request })
})
}
addCDPRequestDataListener('Network.requestWillBeSent')
addCDPRequestDataListener('Network.requestWillBeSentExtraInfo')
addCDPRequestDataListener('Network.responseReceived')
addCDPRequestDataListener('Network.responseReceivedExtraInfo')
return cdpRequestDataRaw
}
That's because your browser sets a bunch of headers depending on settings and capabilities, and also includes e.g. the cookies that it has stored locally for the specific page.
If you want to add additional headers, you can use methods such as:
page.setExtraHTTPHeaders docs here.
page.setUserAgent docs here.
page.setCookies docs here.
With these you can mimic the extra headers that you see your Chrome browser dispatching.
As i am either too dump to find the proper answer or it is simply not out there ... how the hek i replace the "outdated" WebRequest properly with the HttpClient "replacement"?
In the WebRequest i tendet to serialize & analyze the actual cookie as the webpage returns a partial JSON cookie ... however ... i still did not found a way to get a proper CookieContainer (or whatever form of cookie) from the frking HttpClient ... also ... every google request leads me to 20000000 years old answers or outdated documents (+ some upToDate docs which all just refer to "GET" requests without any cookies involved -.-*))
would be kindfull if somebody could lead me to the correct path ...
thx
greets
X39
Windows.Web.Http.HttpClient client = new Windows.Web.Http.HttpClient();
client.DefaultRequestHeaders.UserAgent.TryParseAdd(app.Settings.UserAgent);
var response = await client.PostAsync(new Uri(app.Settings.Pr0grammUrl.Api + "user/login"), new Windows.Web.Http.HttpStringContent(postDataBuilder.ToString()));
By default, HttpClient handles cookies by itself through the default HttpBaseProtocolFilter. You can get cookies associated with a URI through GetCookies method of the HttpCookieManager class:
Gets an HttpCookieCollection that contains the HttpCookie instances
that are associated with a specific URI.
using (var protocolFilter = new HttpBaseProtocolFilter()) {
var cookieManager = protocolFilter.CookieManager;
var cookies = cookieManager.GetCookies(uri);
foreach (var cookie in cookies) {
// Here is each cookie
}
}
You should also be able to set/get cookies through HTTP request and response headers. To disallow HttpClient from handling cookies by itself, create an instance of HttpBaseProtocolFilter and set the CookieUsageBehavior to HttpCookieUsageBehavior.NoCookies:
NoCookies: Do not handle cookies automatically.
// Create http filter
httpFilter = new HttpBaseProtocolFilter();
httpFilter.CookieUsageBehavior = HttpCookieUsageBehavior.NoCookies;
// Create http client
httpClient = new HttpClient(httpFilter);
// Handle cookies through HTTP headers
I have an application using ember-couchdb-kit to interface with a CouchDB instance. I am having difficulty accessing the server after requiring authentication.
I tried cookie authentication and the cookie gets set in the browser, but it isn't sent to the database for subsequent requests according to the network dialog in both Chrome and Firefox.
I don't understand why this is happening, but in the pursuit of getting the application working, I wanted to try HTTP auth.
My document adapter is just:
App.Host = 'http://localhost:5984'
App.ApplicationAdapter = EmberCouchDBKit.DocumentAdapter.extend( { db: 'wells', host: App.Host } )
I want to add the username and password to the URL, so after the user enters them, I run:
EmberCouchDBKit.DocumentAdapter.reopen( {
host: ( function() {
var parts = App.Host.split( '://' )
return "%#://%#:%##%#".fmt( parts[0], $('#username').val(), $('#password').val(), parts[1] )
} )()
} )
The URL for subsequent requests doesn't change though. What do I need to do?
The adapter isn't recreated each time it's used, and reopen only applies to newly created instanes. As such you'll need to redefine it on the already existing adapter instance. Inside a route/controller you could do it like so:
var adapter = this.store.adapterFor('application');
adapter.set('host', 'foobar');
I am currently developing a web app which should do restful service calls to existing web service api.
What I have is the base URL and the API names.
Any help on how do I start working on it?
I suppose I need to use httpbuilder for the base url I have, then followed by /api name. But how do I test it on grails if its working?
When I paste the base url on the browser it does return some xml information, so what I need is to do it on grails instead.
XML response when I paste the url through browser
<ns1:createNewUserResponse>
<userId>21</userId>
</ns1:createNewUserResponse>
So I need to be able to get this response through my web-app (grails) instead of pasting it on the browser.
EDIT*
this is a good example I found useful
#Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.5.0-RC2' )
import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
def http = new HTTPBuilder( 'http://ajax.googleapis.com' )
// perform a GET request, expecting JSON response data
http.request( GET, JSON ) {
uri.path = '/ajax/services/search/web'
uri.query = [ v:'1.0', q: 'Calvin and Hobbes' ]
headers.'User-Agent' = 'Mozilla/5.0 Ubuntu/8.10 Firefox/3.0.4'
// response handler for a success response code:
response.success = { resp, json ->
println resp.statusLine
// parse the JSON response object:
json.responseData.results.each {
println " ${it.titleNoFormatting} : ${it.visibleUrl}"
}
}
// handler for any failure status code:
response.failure = { resp ->
println "Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}"
}
}
but i do not understand the query part and how do I alter it to my need?
the URL I have contains credential of username and password, the response should return a securityToken which I need to get it out from the results. Any help would be greatly appreciated!
You can start with groovy-wslite, it provides both SOAP and REST webservice clients.
To make a call to a resfull service look at Groovy HttpBuidler - http://groovy.codehaus.org/HTTP+Builder