add a proper documentation
featuring an actually working usage example! also: change exports in index.mjs for easier import
This commit is contained in:
parent
dea075a87e
commit
d2e88e3b1a
90
README.md
90
README.md
|
@ -1,13 +1,85 @@
|
||||||
# node-fetch-cookies
|
# node-fetch-cookies
|
||||||
node-fetch wrapper that adds support for cookie-jars
|
A [node-fetch](https://github.com/bitinn/node-fetch) wrapper with support for cookies.
|
||||||
|
It supports reading/writing from/to a JSON cookie jar and keeps cookies in memory until you call `CookieJar.save()` to reduce disk I/O.
|
||||||
|
|
||||||
## Example Usage
|
## Usage Example
|
||||||
```javascript
|
```javascript
|
||||||
import cookies from "node-fetch-cookies";
|
import {fetch, CookieJar} from "node-fetch-cookies";
|
||||||
// "rw" are the flags, meaning cookies will be read and written from/to the cookie jar. r = read, w = write
|
|
||||||
// second argument is the filename, can also be undefined if you don't want to read/write the cookies from/to a file
|
(async () => {
|
||||||
let cookieJar = new cookies.CookieJar("rw", "path/to/file.json");
|
// creates a CookieJar instance
|
||||||
// first parameter is the url, second the options, just like node-fetch. third parameter is the cookie jar (can also be an array)
|
let cookieJar = new CookieJar("rw", "jar.json");
|
||||||
// returns a response object just like node-fetch
|
|
||||||
cookies.fetch("https://example.page/example/path", null, cookieJar);
|
// usual fetch usage, except with one or multiple cookie jars as first parameter
|
||||||
|
const response = await fetch(cookieJar, "https://google.de");
|
||||||
|
|
||||||
|
// save the received cookies to disk
|
||||||
|
cookieJar.save();
|
||||||
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
### fetch(cookieJar, url, options)
|
||||||
|
- `cookieJar` A [CookieJar](#class-cookiejar) instance or an array of CookieJar instances
|
||||||
|
- `url` and `options` as in https://github.com/bitinn/node-fetch#fetchurl-options
|
||||||
|
|
||||||
|
|
||||||
|
### Class: CookieJar
|
||||||
|
A class that stores cookies.
|
||||||
|
|
||||||
|
#### Properties
|
||||||
|
- `flags` The read/write flags as specified below.
|
||||||
|
- `file` The path of the cookie jar on the disk.
|
||||||
|
- `cookies` A [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) mapping cookie names to their properties.
|
||||||
|
|
||||||
|
#### new CookieJar(flags, file[, cookies])
|
||||||
|
- `flags` A string specifying whether cookies should be read and/or written from/to the jar when passing it as parameter to [fetch](#fetchcookiejar-url-options).
|
||||||
|
- `r`: only read from this jar
|
||||||
|
- `w`: only write to this jar
|
||||||
|
- `rw` or `wr`: read/write from/to this jar
|
||||||
|
- `file` A string containing a relative or absolute path to the file on the disk to use.
|
||||||
|
- `cookies` An optional initializer for the cookie jar - either an array of [Cookie](#class-cookie) instances or a single Cookie instance.
|
||||||
|
|
||||||
|
#### addCookie(cookie[, url])
|
||||||
|
Adds a cookie to the jar.
|
||||||
|
- `cookie` A [Cookie](#class-cookie) instance to add to the cookie jar. Alternatively this can also be a string, for example the string received from a website. In this case `url` should be specified.
|
||||||
|
- `url` The url a cookie has been received from.
|
||||||
|
|
||||||
|
#### forEach(callback)
|
||||||
|
Just a wrapper for `CookieJar.cookies.forEach(callback)`.
|
||||||
|
|
||||||
|
#### save()
|
||||||
|
Saves the cookie jar to disk. Only non-expired cookies are saved.
|
||||||
|
|
||||||
|
|
||||||
|
### Class: Cookie
|
||||||
|
An abstract representation of a cookie.
|
||||||
|
|
||||||
|
#### Properties
|
||||||
|
- `name` The identifier of the cookie.
|
||||||
|
- `value` The value of the cookie.
|
||||||
|
- `expiry` A [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object of the cookies expiry date.
|
||||||
|
- `domain` The domain the cookie is valid for.
|
||||||
|
- `path` The path the cookie is valid for.
|
||||||
|
- `secure` A boolean value representing the cookie's secure attribute. If set the cookie will only be used for `https` requests.
|
||||||
|
- `subdomains` A boolean value specifying whether the cookie should be used for subdomains of the domain or not.
|
||||||
|
|
||||||
|
#### new Cookie(cookie, url)
|
||||||
|
- `cookie` The string representation of a cookie as send by a webserver.
|
||||||
|
- `url` The url the cookie has been received from.
|
||||||
|
|
||||||
|
#### static fromObject(obj)
|
||||||
|
Creates a cookie instance from an already existing object with the same properties.
|
||||||
|
|
||||||
|
#### serialize()
|
||||||
|
Serializes the cookie, transforming it to `name=value` so it can be used in requests.
|
||||||
|
|
||||||
|
#### hasExpired()
|
||||||
|
Returns whether the cookie has expired or not.
|
||||||
|
|
||||||
|
#### isValidForRequest(url)
|
||||||
|
Returns whether the cookie is valid for a request to `url`. If not, it won't be send by the fetch wrapper.
|
||||||
|
|
||||||
|
## License
|
||||||
|
This project is licensed under the MIT license, see [LICENSE](LICENSE).
|
||||||
|
|
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "node-fetch-cookies",
|
"name": "node-fetch-cookies",
|
||||||
"version": "1.0.0",
|
"version": "1.0.3",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-fetch": {
|
"node-fetch": {
|
||||||
"version": "2.3.0",
|
"version": "2.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
|
||||||
"integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA=="
|
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "node-fetch-cookies",
|
"name": "node-fetch-cookies",
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"description": "node-fetch wrapper that adds support for cookie-jars",
|
"description": "node-fetch wrapper that adds support for cookie-jars",
|
||||||
"main": "src/index.mjs",
|
"main": "src/index.mjs",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
@ -26,6 +26,6 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/jkhsjdhjs/node-fetch-cookies#readme",
|
"homepage": "https://github.com/jkhsjdhjs/node-fetch-cookies#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-fetch": "^2.3.0"
|
"node-fetch": "^2.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ export default class CookieJar {
|
||||||
// only save cookies that haven't expired
|
// only save cookies that haven't expired
|
||||||
let cookiesToSave = new Map();
|
let cookiesToSave = new Map();
|
||||||
this.forEach(cookie => {
|
this.forEach(cookie => {
|
||||||
if(cookie.expiry && cookie.expiry > new Date())
|
if(!cookie.hasExpired())
|
||||||
cookiesToSave.set(cookie.name, cookie);
|
cookiesToSave.set(cookie.name, cookie);
|
||||||
});
|
});
|
||||||
fs.writeFileSync(this.file, JSON.stringify([...cookiesToSave]));
|
fs.writeFileSync(this.file, JSON.stringify([...cookiesToSave]));
|
||||||
|
|
|
@ -90,8 +90,11 @@ export default class Cookie {
|
||||||
serialize() {
|
serialize() {
|
||||||
return this.name + "=" + this.value;
|
return this.name + "=" + this.value;
|
||||||
}
|
}
|
||||||
|
hasExpired() {
|
||||||
|
return this.expiry && this.expiry < new Date();
|
||||||
|
}
|
||||||
isValidForRequest(url) {
|
isValidForRequest(url) {
|
||||||
if(this.expiry && this.expiry < new Date())
|
if(this.hasExpired())
|
||||||
return false;
|
return false;
|
||||||
const parsedURL = urlParser.parse(url);
|
const parsedURL = urlParser.parse(url);
|
||||||
if(parsedURL.protocol !== "http:" && parsedURL.protocol !== "https:")
|
if(parsedURL.protocol !== "http:" && parsedURL.protocol !== "https:")
|
||||||
|
|
|
@ -2,54 +2,52 @@ import fetch from "node-fetch";
|
||||||
import CookieJar from "./cookie-jar";
|
import CookieJar from "./cookie-jar";
|
||||||
import Cookie from "./cookie";
|
import Cookie from "./cookie";
|
||||||
|
|
||||||
export default {
|
async function cookieFetch(cookieJars, url, options) {
|
||||||
fetch: async (url, options, cookieJars) => {
|
let cookies = "";
|
||||||
let cookies = "";
|
if(Array.isArray(cookieJars) && cookieJars.every(c => c instanceof CookieJar)) {
|
||||||
if(Array.isArray(cookieJars) && cookieJars.every(c => c instanceof CookieJar)) {
|
cookieJars.forEach(jar => {
|
||||||
cookieJars.forEach(jar => {
|
if(!jar.flags.includes("r"))
|
||||||
if(!jar.flags.includes("r"))
|
return;
|
||||||
return;
|
jar.forEach(c => {
|
||||||
jar.forEach(c => {
|
|
||||||
if(c.isValidForRequest(url))
|
|
||||||
cookies += c.serialize() + "; ";
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if(cookieJars instanceof CookieJar && cookieJars.flags.includes("r")) {
|
|
||||||
cookieJars.forEach(c => {
|
|
||||||
if(c.isValidForRequest(url))
|
if(c.isValidForRequest(url))
|
||||||
cookies += c.serialize() + "; ";
|
cookies += c.serialize() + "; ";
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if(cookieJars instanceof CookieJar && cookieJars.flags.includes("r")) {
|
||||||
|
cookieJars.forEach(c => {
|
||||||
|
if(c.isValidForRequest(url))
|
||||||
|
cookies += c.serialize() + "; ";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new TypeError("Third paramter is neither a cookie jar nor an array of cookie jars!");
|
||||||
|
if(cookies.length !== 0) {
|
||||||
|
if(!options) {
|
||||||
|
options = {
|
||||||
|
headers: {}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else
|
else if(!options.headers)
|
||||||
throw new TypeError("Third paramter is neither a cookie jar nor an array of cookie jars!");
|
options.headers = {};
|
||||||
if(cookies.length !== 0) {
|
options.headers.cookie = cookies.slice(0, -2);
|
||||||
if(!options) {
|
}
|
||||||
options = {
|
const result = await fetch(url, options);
|
||||||
headers: {}
|
// i cannot use headers.get() here because it joins the cookies to a string
|
||||||
};
|
cookies = result.headers[Object.getOwnPropertySymbols(result.headers)[0]]["set-cookie"];
|
||||||
}
|
if(cookies) {
|
||||||
if(!options.headers)
|
if(Array.isArray(cookieJars)) {
|
||||||
options.headers = {};
|
cookieJars.forEach(jar => {
|
||||||
options.headers.cookie = cookies.slice(0, -2);
|
if(!jar.flags.includes("w"))
|
||||||
|
return;
|
||||||
|
cookies.forEach(c => jar.addCookie(c, url));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const result = await fetch(url, options);
|
else if(cookieJars.flags.includes("w")) {
|
||||||
// i cannot use headers.get() here because it joins the cookies to a string
|
cookies.forEach(c => cookieJars.addCookie(c, url));
|
||||||
cookies = result.headers[Object.getOwnPropertySymbols(result.headers)[0]]["set-cookie"];
|
|
||||||
if(cookies) {
|
|
||||||
if(Array.isArray(cookieJars)) {
|
|
||||||
cookieJars.forEach(jar => {
|
|
||||||
if(!jar.flags.includes("w"))
|
|
||||||
return;
|
|
||||||
cookies.forEach(c => jar.addCookie(c, url));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if(cookieJars.flags.includes("w")) {
|
|
||||||
cookies.forEach(c => cookieJars.addCookie(c, url));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
},
|
return result;
|
||||||
CookieJar: CookieJar,
|
}
|
||||||
Cookie: Cookie
|
|
||||||
};
|
export {cookieFetch as fetch, CookieJar, Cookie};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user