add a proper documentation

featuring an actually working usage example!

also: change exports in index.mjs for easier import
This commit is contained in:
jkhsjdhjs 2019-06-16 00:06:28 +02:00
parent dea075a87e
commit d2e88e3b1a
Signed by: jkhsjdhjs
GPG Key ID: BAC6ADBAB7D576CC
6 changed files with 136 additions and 63 deletions

View File

@ -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
View File

@ -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=="
} }
} }
} }

View File

@ -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"
} }
} }

View File

@ -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]));

View File

@ -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:")

View File

@ -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};