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 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
import cookies 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
let cookieJar = new cookies.CookieJar("rw", "path/to/file.json");
// first parameter is the url, second the options, just like node-fetch. third parameter is the cookie jar (can also be an array)
// returns a response object just like node-fetch
cookies.fetch("https://example.page/example/path", null, cookieJar);
import {fetch, CookieJar} from "node-fetch-cookies";
(async () => {
// creates a CookieJar instance
let cookieJar = new CookieJar("rw", "jar.json");
// 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",
"version": "1.0.0",
"version": "1.0.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"node-fetch": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz",
"integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA=="
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
}
}
}

View File

@ -1,10 +1,10 @@
{
"name": "node-fetch-cookies",
"version": "1.0.2",
"version": "1.0.3",
"description": "node-fetch wrapper that adds support for cookie-jars",
"main": "src/index.mjs",
"engines": {
"node": ">=10.0.0"
"node": ">=10.0.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
@ -26,6 +26,6 @@
},
"homepage": "https://github.com/jkhsjdhjs/node-fetch-cookies#readme",
"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
let cookiesToSave = new Map();
this.forEach(cookie => {
if(cookie.expiry && cookie.expiry > new Date())
if(!cookie.hasExpired())
cookiesToSave.set(cookie.name, cookie);
});
fs.writeFileSync(this.file, JSON.stringify([...cookiesToSave]));

View File

@ -90,8 +90,11 @@ export default class Cookie {
serialize() {
return this.name + "=" + this.value;
}
hasExpired() {
return this.expiry && this.expiry < new Date();
}
isValidForRequest(url) {
if(this.expiry && this.expiry < new Date())
if(this.hasExpired())
return false;
const parsedURL = urlParser.parse(url);
if(parsedURL.protocol !== "http:" && parsedURL.protocol !== "https:")

View File

@ -2,54 +2,52 @@ import fetch from "node-fetch";
import CookieJar from "./cookie-jar";
import Cookie from "./cookie";
export default {
fetch: async (url, options, cookieJars) => {
let cookies = "";
if(Array.isArray(cookieJars) && cookieJars.every(c => c instanceof CookieJar)) {
cookieJars.forEach(jar => {
if(!jar.flags.includes("r"))
return;
jar.forEach(c => {
if(c.isValidForRequest(url))
cookies += c.serialize() + "; ";
});
});
}
else if(cookieJars instanceof CookieJar && cookieJars.flags.includes("r")) {
cookieJars.forEach(c => {
async function cookieFetch(cookieJars, url, options) {
let cookies = "";
if(Array.isArray(cookieJars) && cookieJars.every(c => c instanceof CookieJar)) {
cookieJars.forEach(jar => {
if(!jar.flags.includes("r"))
return;
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))
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
throw new TypeError("Third paramter is neither a cookie jar nor an array of cookie jars!");
if(cookies.length !== 0) {
if(!options) {
options = {
headers: {}
};
}
if(!options.headers)
options.headers = {};
options.headers.cookie = cookies.slice(0, -2);
else if(!options.headers)
options.headers = {};
options.headers.cookie = cookies.slice(0, -2);
}
const result = await fetch(url, options);
// 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(Array.isArray(cookieJars)) {
cookieJars.forEach(jar => {
if(!jar.flags.includes("w"))
return;
cookies.forEach(c => jar.addCookie(c, url));
});
}
const result = await fetch(url, options);
// 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(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));
}
else if(cookieJars.flags.includes("w")) {
cookies.forEach(c => cookieJars.addCookie(c, url));
}
return result;
},
CookieJar: CookieJar,
Cookie: Cookie
};
}
return result;
}
export {cookieFetch as fetch, CookieJar, Cookie};