elbywan / wretch Goto Github PK
View Code? Open in Web Editor NEWA tiny wrapper built around fetch with an intuitive syntax. :candy:
License: MIT License
A tiny wrapper built around fetch with an intuitive syntax. :candy:
License: MIT License
I'd like to decorate the response
object with some custom data after an original request retry resolves. Something like this:
const refreshAndRetry = async (error, originalRequest) => {
const token = await wretch()
.url('/auth/refresh')
.get()
.json();
return originalRequest
.resolve(resolver =>
resolver.res(response => {
response.token = token;
return response;
})
)
.auth(`Bearer ${token}`)
.get()
.unauthorized(error => {
throw error;
})
.json();
};
As you can see - I'd like to have a response.token
property on a request which had to refresh the token and retry. I need this to handle fresh tokens somewhere in the higher level of the application.
Unfortunately the above code throws a originalRequest.resolve(...).auth(...).get(...).unauthorized is not a function
error.
Could you please help and tell me what I'm doing wrong and how can I solve this?
Use AbortController to add timeout and abort features.
Something like :
let w = wretch("...")
.signal("...") // optional - ability to use a custom AbortSignal to abort multiple requests
.get()
// before the fetch() call, the signal should be injected by wretch
// if no signal was added, wretch creates an AbortController for the request
.setTimeout(number /* aborts after N milliseconds */)
.onAbort(AbortError => /* new catcher for aborted requests */)
let [ c, w ] = w.controller() /* ugly :( but seems like there is no better way of doing things */
w.res(r => /* should never be called ... */)
c.abort()
I've just started using wretch and noticed the nice feature that allows adding custom middlewares for implementing cross-cutting concerns like caching, as you've nicely illustrated in the docs. Many times, there is a need for adding support for retry mechanism. Would it be possible to illustrate in a sample how a request retry middleware would look like?
If I do a simple POST I have no problems:
wretch(url)
.json(jsonMessage)
.post()
.res()
.catch(error => console.log(error))
The moment I try to use the timeout syntactic sugar (and setting a timeout) like this:
wretch(url)
.json(jsonMessage)
.post()
.setTimeout(1000)
.timeout(err => console.log(err.status))
.res()
.catch(error => console.log(error))
I get the following error and I can't figure out why:
TypeError: Cannot read property 'abort' of undefined
resolver.ts:128
at Timeout._onTimeout (/Users/ebuchan/Source/Repos/slackapp-ops/node_modules/wretch/dist/bundle/wretch.js:1:4954)
at ontimeout (timers.js:498:11)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)
When I import wretch according to the test file and polyfill it as the following,
import * as formData from 'form-data';
import { URLSearchParams } from 'url';
import nodeFetch from 'node-fetch';
import wretch from 'wretch';
wretch().polyfills({
fetch: nodeFetch,
FormData: formData,
URLSearchParams,
});
it complain that wretch.default is not a function when build with tsc.
wretch.default().polyfills({
TypeError: wretch.default is not a function
And when i change it to the syntax below,
import * as wretch from 'wretch';
it works, but the linter is complaining...
[ts] Cannot invoke an expression whose type lacks a call signature.
So what I do now is
import * as wretch from 'wretch';
import { Wretcher } from 'wretch/dist/wretcher';
((wretch as any)() as Wretcher).polyfills({
fetch: nodeFetch,
FormData: formData,
URLSearchParams,
});
so that the type definition and tsc build
keep working again.
Is there anything wrong with my syntax? Or is there any compiler option that is causing this?
Hi @elbywan, first of all thank for your nice work.
I could not find a way to catch network errors (net::ERR_NAME_NOT_RESOLVED -> failed to fetch) in cors mode. Using a middleware I can log them. Imagine the exampe below:
const logMiddleware = () => next => (url, opts) => {
console.log(opts.method + "@" + url);
return next(url, opts);
}
const wretchRequest = wretch()
.options({ credentials: 'include', mode: 'cors' })
.options({ headers: { Accept: 'application/json' } })
.middlewares([
logMiddleware()
]);
wretchRequest
// AN INVALID URL (to provoke network failure)
.url(`http://qsdkjlkjqslkdjlkqjsldkjqs.com/auth/token`)
.options({ mode: 'cors' })
.post({
email: email,
password: password,
})
.json(response => {
// Here some code.
})
.catch(error => {
alert('THE NETWORK ERROR SHOULD BE REPORTED HERE ?');
alert('UNFORTUNATELY, IT DOES NOT');
});
The logMiddleware correctly shows the failure during the 'pre-flight/option request',
> OPTIONS http://qsdkjlkjqslkdjlkqjsldkjqs.com/auth/token net::ERR_NAME_NOT_RESOLVED
> Login error TypeError: Failed to fetch
But it's not reaching the catch block. Any Idea how to handle this in the catch ?
I will preface by saying: @elbywan thanks your work on this project. It has made working with fetch so much more palatable, and the usability of this abstraction is wonderful.
I have some code that looks like this:
async function refresh() {
const accessToken = getAccessToken();
try {
await wretch(`path/to/oauth/refresh`)
.options({
credentials: 'include',
})
.auth(`Bearer ${accessToken}`)
.get()
.catch((e) => {
// this is never called
debugger;
});
} catch (e) {
// this is also never called
debugger;
}
debugger;
}
I'm testing a flow where a user's refresh token is absent or invalid, and so I expect this refresh endpoint to fail with a 400. When I call refresh()
, it seems that the third debugger statement is encountered first, and what is more, the Promise returned by Wretch hasn't even returned yet. In fact, the two other debugger statements are never even encountered, even when the request returns as a 400.
I must be missing something about the control flow of Wretch. Does anything stick out?
Hi!
Firstly, thanks for a great library - really useful!
I would like to create a custom middleware, which would call the same request again at a later time (as interval - for polling). For example: in options() I would specify needed behavior:
return .api
.url(urlPath)
.options({
refetchDelay: 2000,
refetchUntil: () => this.refetchEnabled
})
.get()
.json(({ data }) => {
this.applications.set(data);
});
The problem is that a single request should be able to produce multiple requests. Having something like this works that it refetches the request, but the callback (json()) is not being executed (not being resolved):
export const refetch: RefetchMiddleware = () => {
return next => (url, opts) => {
const refetchRequest = (response: any): any => {
const refetchDelay = opts.refetchDelay || defaultDelay;
const refetchUntil = opts.refetchUntil || defaultUntil;
if (refetchUntil()) {
return new Promise(resolve => {
setTimeout(() => {
resolve(next(url, opts).then(refetchRequest));
}, refetchDelay);
}).then(refetchRequest);
}
return response;
};
return next(url, opts).then(refetchRequest);
};
};
Thoughts?
Thanks,
Mitja
Hi, thanks for this great library.
I don't know whether this should be considered as a bug, but I see that timeout timers are not cleared even if the request promise has been resolved or rejected. Here is the relevant code line.
If you need an idea of how this can be fixed look at the following axios code snippet.
I think it's important to clear timers so that resources are not wasted without any purpose. As far as I can see, to implement this feature we need to call clearTimeout
in the following cases:
abort
I just came across wretch. And from the description, it sounded a bit like r2 for example.
When it comes to xmlhttprequest/fetch wrappers I'm always asking myself, how is this framework different from the others? I could still use axiom for example. Sure it still uses the oldie but goldie xmlhttprequest instead of fetch. But it also handles the 404 stuff and json repsonses and so on.
Some web applications use non-standard query strings that aren't necessarily an ampersand-separated list of keys and urlencoded values.
wretch should allow this case by accepting a string value in .query()
and appending that to the URL after the ?
verbatim.
I'm working on a mobile hybrid app. When the user is offline and the request fails fetch does not throw an error but neither does wretch. What happens is that the response is considered ok and it obviously can't be json parsed.
When using fetch it's common to use the response.ok
flag to prevent this but from what I've seen this is not available in wretch.
What is the appropriate solution to this with wretch?
Should wretch throw an error when the ok flag is false?
Is there a way I can access the native fetch response?
Hi and thanks for the awesome lib!
Is there a way to get response headers when using wretch? I wasn't able to find anything in the docs.
Hey,
From the documentation:
wretch("...").get().json(() => "Hello world!").then(console.log) // Hello world!
This does not work if the returned value is false
or null
(probably any falsy value), the original request is passed on to the next promise instead.
I took a quick look at the source and I believe it's caused by how the callback is run here
https://github.com/elbywan/wretch/blob/master/src/resolver.ts#L89-L92
I'm not sure if it's an intentional choice, so when the callback does not return you won't lose the original request, or a bug. Even if it's intentional it might be better to explicitly check if the return value is undefined
as returning some kind of "success" boolean might be a common use case.
Fortunately the workaround is pretty straight-forward:
wretch("...").get().json().then(() => false).then(console.log)
Thanks for this very nice library btw!
First, great little library thanks for the work.
Question, what is main diference between middleware / resolvers, when one should be used vs another?
Thanks.
Taking some inspiration from axios. It would be nice to have middleware for caching and throttling requests.
Hi
Is there a way to enable an error to be passed to a response handler? for example have the res() object status equal to the error code?
In any case, thanks for this amazing library!
Hey there. Loving usage of wretch. So simple to use.
I have a call to an endpoint where it was hitting the timeout, but it was not using the timeout syntactic sugar, but instead being caught by the catch().
wretch
.url(endpoint)
.formUrl(form)
.post()
.setTimeout(8000)
.timeout(error => console.log('Timeout for ' + endpoint + ' ' + error))
.json(response => console.log(response)
.catch(error => console.log('Error: ' + error))
The endpoint had started failing as it was being slow. In this case I was getting as below indicating the .timeout
isn't catching the abort from the 8000ms.
Error: AbortError: Aborted for /sdpapi/request?format=json
When I bumped the timeout to 20000ms It logged the response. Stupid software upgrade on the target system made it much slower :(
Shouldn't .timeout()
catch the abort?
Hi!
I very like this library, I was missing such a wrapper over fetch
👍
The problem that I have is that currently using fetch, I developed my services
to optionally accept AbortSignal
as a parameter to control cancellation from the outside. This library doesn't accept AbortSignal
but AbortController
- by doing this is not compatible with fetch
implementation.
Is there a reason why you implemented it that way?
The fragment that is responsible for that is:
/**
* Associates a custom signal with the request.
* @param controller : An AbortController
*/
signal(controller: AbortController) {
return this.selfFactory({ options: { ...this._options, signal: controller.signal }})
}
My suggestion is to change it to:
/**
* Associates a custom signal with the request.
* @param signal : An AbortSignal
*/
signal(signal: AbortSignal) {
return this.selfFactory({ options: { ...this._options, signal }})
}
Unfortunately it would introduce a breaking change. What do you think about it? 😃
I've noticed the readme uses res()
in a few places, without using the response (I mean .res(response => do something here with response)
). Here's one example:
wretch().url("...").get().json(/* ... */)
// Can be used to set a base url
// Subsequent requests made using the 'blogs' object will be prefixed with "http://mywebsite.org/api/blogs"
const blogs = wretch("http://mywebsite.org/api/blogs")
// Perfect for CRUD apis
const id = await blogs.post({ name: "my blog" }).json(_ => _.id)
const blog = await blogs.url(`/${id}`).get().json()
console.log(blog.name)
await blogs.url(`/${id}`).delete().res()
// And to replace the base url if needed :
const noMoreBlogs = blogs.url("http://mywebsite.org/", true)
I'd like to understand what res()
does at the end of await blogs.url(`/${id}`).delete().res()
.
Hi @elbywan, I have a similar use case like #16 but instead of retrying automatically I want to wait for the user to press a button before running the next request.
I try to use the replay() method as in the docs originalRequest.replay()
but it does not have the same resolver as the original one;
Can you show me how to achieve this?
First of all, awesome API!
this works wretch().get().error()
but not this wretch().error().get()
gives .error is not a function
.
How can I setup a default error handler, before calling get/post/etc?
Something like time: true
in [request][https://www.npmjs.com/package/request].
Hi,
I have an issue when using your library on a typescript project using webpack.
When I call Post, I have this error in Chrome :
TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
After looking for the error on google, I came across this issue which I think is similar.
Hi @elbywan, thanks a lot for your work !
I face a weird error with Firefox (no errors happen in Chrome and Safari), which cause the browser to refresh.
Do you know the origin of the problem ? Format of body ?
Thanks a lot for your help !
const addAuthTokenMiddleware = next => (url, opts) => next(url, {
...opts,
headers: {
...opts.headers,
Authorization: `Bearer ${getToken()}`,
},
});
const defaultWretch = wretch()
.url('/api')
.options({ credentials: 'include' })
.middlewares([addAuthTokenMiddleware]);
const response = defaultWretch
.url(url)
.post(body)
.json()
.catch(error => {
console.error('Clovis ServerApiJSON post error :', {
error: error,
url: url,
body: body,
});
});
https://runkit.com/embed/gh39bs0gaifx:
var wretch = require("wretch");
var qs = require("qs");
const convertFormUrl = (formObject) => {
return Object.keys(formObject)
.map(key =>
encodeURIComponent(key) + "=" +
`${ encodeURIComponent(typeof formObject[key] === "object" ? JSON.stringify(formObject[key]) : formObject[key]) }`)
.join("&")
};
const obj = {'a': [1, 2]};
console.log(convertFormUrl(obj), unescape(convertFormUrl(obj)));
console.log(qs.stringify(obj), unescape(qs.stringify(obj)));
==>
"a=%5B1%2C2%5D"
"a=[1,2]" // wretch
"a%5B0%5D=1&a%5B1%5D=2"
"a[0]=1&a[1]=2" // qs
I expect something like the second.
Hey, I really the lib but I think I found a strange behavior.
I would like to avoid sending the Referrer
header but it doesn't seem to work as expected.
My instance is like this:
var apiRoot = wretch(root)
.options({credentials: "include", mode: "cors", referrer: 'no-referrer'})
.content("application/json")
.accept("application/json")
And when I do apiRoot.get().json()
, the Referrer
header is set to Referer: http://localhost:8080/apps/no-referrer
I also tried with false
and null
, but the string version is added to the root url.
Am I doing something wrong? I know fetch
accepts that option.
Thanks
On my actual project, I use wretch.
Don't get me wrong, wretch is awesome: it is one of the best designed fetch wrapper I have seen so far and I have been using so far and I've been using a few (XMLHTTPRequest direct, axios, request, superagent, fetch directly, frisbee and now wretch).
Before everything, thank you. 😍
.query()
is misleading. It try to handle stringification / url encoding of javascript object and manage to do it well for 80% of the cases (common one) but fails the complex one.
On my project for instance we have done:
wretch("https://example.com/test").query({ pagination: { pageSize: 25, page: 1 }}).get()
which outputed : https://example.com/test?pagination[object Object]
😱
That cause us a bug and took a while to debug (2h or so).
I plan to improve wretch so users does not have to be wretch finding bugs.
For me the reference implementation is https://github.com/ljharb/qs and looking at https://github.com/ljharb/qs/blob/master/test/stringify.js it supports the following features (checkbox checked if wretch support it right now)
a=b
-> a=b
{ a: '€' }
-> 'a=%E2%82%AC'
{ 'a a': 'b 'b'}
-> 'a+a=b+b'
{ a: { b: 'c' } }
-> 'a%5Bb%5D=c'
{ a: { b: 'c' }
-> 'a.b=c'
{ a: ['b', 'c']}
-> 'a[0]=b&a[1]=c'
{ a: ['b', 'c']}
-> 'a=b&a=c'
{ a: ['b', 'c']}
-> 'a[]=b&a[]=c'
{ a: 'b', c: null}
-> 'a=b
If it is ok for you:
I'm support use to contributing to repo with prettier activated. Here I needed to deactivate it then do the formatting by hand which is painful now that I get use to format.
Would you mind an other PR to include prettier and configure it to be the less different to actual source code ?
The reAuthOn401
example in the readme is just what I was looking for, but I had to adjust it a little to work correctly. The original:
const reAuthOn401 = wretch()
.catcher(401, async (error, request) => {
const token = await wretch("/renewtoken").get().text()
storeToken(token)
// The return of `.replay()` is just a vanilla Promise, which has no `.unauthorized()` method
return request.auth(token).replay().unauthorized(err => { throw err }).json()
})
Updated:
const reAuthOn401 = wretch()
.catcher(401, async (error, request) => {
const token = await wretch("/renewtoken").get().text()
storeToken(token)
return request
.auth(token)
.catcher(401, (errInner, reqInner) => {
throw errInner;
})
.replay()
.then(resp => resp.json());
})
Unless I'm missing something?
Also, thanks for making the fetch library I always wanted!
Hey, great library!
Question: I've set up a reusable wretch
instance that looks somewhat like the following. Also, I'm having a weird time using wretch
without having to use default
, see below:
const wretch = require("wretch").default;
const csrfMiddleware = next => (url, opts) => {
const csrfToken = window.localStorage.getItem("csrfToken");
opts.headers = { ...opts.headers, "x-csrf-token": csrfToken };
return next(url, opts);
};
export const apiFetch = wretch()
.url(`/v1`)
.accept("application/json")
.content("application/json")
.options({
credentials: "same-origin"
})
.middlewares([csrfMiddleware])
.resolve(resolver => resolver
.res(response => {
window.localStorage.setItem("csrfToken", response.headers.get("x-csrf-token"));
return response.json();
})
.catch(error => {
window.localStorage.setItem("csrfToken", error.response.headers.get("x-csrf-token"));
throw error;
})
);
Then, when I try to use the notFound
catcher in a subsequent call, it errors, saying that the function chain with notFound
in it is not a function:
return apiFetch
.url(`/foo`)
.query({
foo: 'bar'
})
.get()
.notFound(() => {
return {
foo: `quux`
};
}) // this results in Uncaught TypeError: apiFetch.url(...).query(...).get(...).notFound is not a function
.then(json => json)
.catch(error => {
console.error(error);
});
Any suggestions on the right way to accomplish what I'm doing here?
Example :
// Old way : with baseUrl
const w = wretch().baseUrl("http://prefix.com/data")
w("/1").get()
w("/2").get()
// Oops ...
w.baseUrl("http://prefix.com/data/subdata")("/1").get()
// New way : With a flag ?
const w = wretch("http://prefix.com/data")
w.url("/1", true).get()
w.url("/2", true).get()
w.url("/subdata", true).url("/1", true).get()
// New way : Or with a new method ?
const w = wretch("http://prefix.com/data")
w.addUrl("/1").get()
w.addUrl("/1").get()
w.addUrl("/subdata").addUrl("/1").get()
// Or both ?
// Or simply make .url append instead of replacing urls ?
// My favourite, even if it's a breaking change I feel like it's more intuitive this way
const w = wretch("http://prefix.com/data")
w.url("/1").get()
w.url("/2").get()
w.url("/subdata").url("/1").get()
// With a 'replace' flag
w.url("http://test.com/", true)
Hi! I have read the docs and peeked at the source and I have a few questions.
defer
in principle a "managed" (wretcher instead of fetchlike) version of middlewares? It feels much easier to configure the wretcher instead of dotting into the options of middlewares.I need something like this:
wretch()
.defer(async w => {
const token = await this.getAccessToken() // <--- lazy retrieval
return w.auth('Bearer ' + token)
})
With middleware I have this code (based on your sample code from other issues):
wretch()
.middlewares([next => async (url, opts) => {
const token = await this.getAccessToken()
if (token) {
return next(url, {
...opts,
headers: {
...opts.headers || {},
Authorization: 'Bearer ' + token
}
})
}
return next(url, opts)
}]
getAccessToken ensures deduping, caching, refreshing token, etc. So I only need to call this in an async context. With an async defer it would be so simple to write. How feasible is this?
Thanks!
Just started using wretch and I really like the API. Currently building a large app, with a micro service architecture, and really appreciate how you can reuse a wretch object for each micro service component, with very small variations for each endpoint.
One thing that I'm missing, that would be convenient, is to have the complete wretch object for a given request, passed as an argument to the callback of any catcher.
The scenario I'm trying to address is primarily HTTP 401 responses, where my access token have expired. In that case, I would like to have a callback that can refresh the token, and then take the failed request and replay it (but with a new access token).
Pseudo-code example:
wretch("...")
.get()
.unauthorized((err, req) => {
const token = getNewToken();
// Replay the failed request, with the new token
const response = req.auth(`Bearer ${token}`).json()
})
Not the most useful example, but I believe it shows what I'm after.
What do you think about that?
From the documentation:
// Or the non-global way :
wretch().polyfills({
fetch: require("node-fetch"),
FormData: require("form-data"),
URLSearchParams: require("url").URLSearchParams
})
There is a single config object shared between the wretch()
instances, which means that it is currently impossible to use different fetch
polyfills for each instance.
The use case would be to handle cookie headers for different APIs in Node.js.
eg.
class API {
constructor (url) {
this.api = wretch()
.url(url)
.options({ credentials: 'include', redirect: 'follow', cache: 'no-store' })
// Node.js environment
if (typeof window === 'undefined') {
const { CookieJar } = eval('require')('tough-cookie')
const jar = new CookieJar()
const fetch = eval('require')('./node/fetch')({ jar })
const { Headers, Request } = fetch
this.api.polyfills({
fetch,
FormData: eval('require')('form-data'),
URLSearchParams: eval('require')('url').URLSearchParams,
})
}
}
Hello,
Can wretch handle all other errors beside the one that I specify?
e.g.
wretch().url(...).post(....)
.unauthorized(_=>{...})
.internalError(_=>{...})
.allOtherErrors(_=>{...})
I set the auth header like this which works fine:
api.auth(`Bearer ${ token }`);
On some requests I need to pass headers, but not others. I have a generic method for doing POST requests so sometimes headers
is undefined and it seems the Authorization
header is removed:
api.headers(headers)
I've resorted to doing this:
api.headers(headers || {})
It works, but it doesn't seem like .headers()
should be messing with the auth header set with .auth()
, no?
This part of code
private selfFactory({ url = this._url, options = this._options, catchers = this._catchers,
resolvers = this._resolvers, middlewares = this._middlewares, deferredChain = this._deferredChain } = {}) {
return new Wretcher(url, options, catchers, resolvers, middlewares, deferredChain)
}
cause new wretches instance use its parent middlewares, resolvers ... this optimization cause weird issue with following part
/**
* Catches an http response with a specific error code or name and performs a callback.
*/
error(errorId, cb) {
catchers.set(errorId, cb)
return responseChain
},
which cause parent object to use error handlers from new wretches instances
for example
/**
Mutate original this.ap1Endpoint and it start use error handler from new instance
This code fix problem
this.ap1Endpoint.catcher(404, (() => undefined)),
but you can get rid of all such problems if selfFactory won't use objects from parent, instead it could do a shallow copy of all required properties
This is my code:
wretch(`${ENDPOINT}/people`)
.post({
person: {
family_name: this.formData.lastName,
given_name: this.formData.firstName,
email_addresses: [
{
address: this.formData.email
}
]
}
})
.res(res => {
this.loading = false
this.sucess = true
})
.catch(err => {
this.loading = false
this.error = err
})
This is the network request that my browser submits:
Request URL:https://ENDPOINT/people
Request method:OPTIONS
Remote address:etc.:443
Status code: 200
Version:HTTP/2.0
Referrer Policy:no-referrer-when-downgrade
It also results in a CORS error, despite the server having its origin policy set to *
:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://ENDPOINT/people. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
This request functions just fine in my REST client.
Hey there! This looks like a nice lib. Good work so far!
I wanted to know, if wretch is good with async/await. Since res
is a callback and not a promise. Does wretch return a promise?
Sets the content encoding header to "application/x-www-form-urlencoded" and sets the body.
// With a string
wretch("myurl").formUrl("say=Hi&to=Mom").post()
// Provide a simple way to serialize objects (no funky stuff)
wretch("myurl").formUrl({ say: "Hi", to: "Mom"}).post()
This is my new favorite HTTP client.
Wondering if there's any Roadmap of features to implement before wretch reaches 1.0
It would be nice to be able to set a baseUrl in the defaults, similar to how you can in axios:
var instance = axios.create({
baseURL: 'https://api.example.com'
});
Awesome work, this library is just what I have been looking for!
Hi,
When building our source with gulp and we use 'gulp-uglify' the following error occurs:
GulpUglifyError: unable to minify JavaScript
Caused by: SyntaxError: Unexpected token: keyword (const)
File: C:\dev\static\build\js\app.min.js
Line: 26603
line 26603
: !function(t,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):t.wretch=r()}(this,function(){"use strict";const t=Objec
....
Thank you!
Jan
Is proxy
(http[s]_proxy) supported ? Since many of us use this behind corporate firewall, it would be great if that can be done.
On the "New Release" page, GitHub suggesting reading about semantic versioning
DO NOT SHIP BREAKING CHANGES IN MINOR RELEASES.
Simple as that.
Don't be afraid of numbers, they are here to help us. Use numbers properly and have a nice day.
Is there a way to use a proxy?
Normally, I would setup a HttpsProxyAgent
then pass that as agent
to https.get()
Hello!
Great work for this little package. I like the way it normalizes behaviors.
I'm currently having a problem with setting the wretch().auth()
dynamically. Before I'm connecting, I don't have things to put into wretch().auth()
but when I'm connected, I have a token that I could not bind to wretch().auth()
because it doesn't run on every requests.
Any idea?
So I'd like to create an app-wide wretch
instance which will retry requests on unauthorized
statuses. It would be pretty easy with wretch
, but unfortunately, I don't really know how do I replay the same specific request.
Because actually sending the request requires a call to .get()
, .post()
or whatever method it was, I can't replay the same request having a global instance.
Am I missing something? Is there a way to send the request without calling the .[httpMethod]()
function?
Hi @elbywan, wretch simplifies my code dramatically. thanks a lot.
btw, in some cases, I have to use DELETE method with the body.
For now it seems that sending a body using the DELETE method
on wretch is not allowed.
I guess DELETE with body is not prohivited by the regulation.
so if I write some PRs, could you accept it? does this make sense?
thanks.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.