Skip to content

Commit ce739f9

Browse files
committed
initial commit
0 parents  commit ce739f9

23 files changed

+4829
-0
lines changed

.gitignore

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
### https://raw.github.com/github/gitignore/608690d6b9a78c2a003affc792e49a84905b3118/Node.gitignore
2+
3+
# Logs
4+
logs
5+
*.log
6+
7+
# Runtime data
8+
pids
9+
*.pid
10+
*.seed
11+
12+
# Directory for instrumented libs generated by jscoverage/JSCover
13+
lib-cov
14+
15+
# Coverage directory used by tools like istanbul
16+
coverage
17+
18+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
19+
.grunt
20+
21+
# node-waf configuration
22+
.lock-wscript
23+
24+
# Compiled binary addons (http://nodejs.org/api/addons.html)
25+
build/Release
26+
27+
# Dependency directory
28+
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
29+
node_modules
30+
31+
# Debug log from npm
32+
npm-debug.log
33+
34+
35+
### https://raw.github.com/github/gitignore/608690d6b9a78c2a003affc792e49a84905b3118/Global/JetBrains.gitignore
36+
37+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
38+
39+
*.iml
40+
41+
## Directory-based project format:
42+
.idea/
43+
# if you remove the above rule, at least ignore the following:
44+
45+
# User-specific stuff:
46+
# .idea/workspace.xml
47+
# .idea/tasks.xml
48+
# .idea/dictionaries
49+
50+
# Sensitive or high-churn files:
51+
# .idea/dataSources.ids
52+
# .idea/dataSources.xml
53+
# .idea/sqlDataSources.xml
54+
# .idea/dynamic.xml
55+
# .idea/uiDesigner.xml
56+
57+
# Gradle:
58+
# .idea/gradle.xml
59+
# .idea/libraries
60+
61+
# Mongo Explorer plugin:
62+
# .idea/mongoSettings.xml
63+
64+
## File-based project format:
65+
*.ipr
66+
*.iws
67+
68+
## Plugin-specific files:
69+
70+
# IntelliJ
71+
out/
72+
73+
# mpeltonen/sbt-idea plugin
74+
.idea_modules/
75+
76+
# JIRA plugin
77+
atlassian-ide-plugin.xml
78+
79+
# Crashlytics plugin (for Android Studio and IntelliJ)
80+
com_crashlytics_export_strings.xml
81+
crashlytics.properties
82+
crashlytics-build.properties
83+
84+
85+
/lib

.travis.yml

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
sudo: false
2+
language: node_js
3+
node_js: "stable"

LICENSE

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2018 azu
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

README.md

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# har-extractor
2+
3+
A CLI that extract har file to directory.
4+
5+
## Install
6+
7+
Install with [npm](https://www.npmjs.com/):
8+
9+
npm install har-extractor -g
10+
# or
11+
npx har-extractor [input]
12+
13+
## Usage
14+
15+
Usage
16+
$ har-extractor <harfile> --output /path/to/output
17+
18+
Options:
19+
--output, -o Output directory
20+
--dry-run Enable dry run mode
21+
--verbose Show processing file path
22+
23+
Examples
24+
$ har-extractor ./net.har --output /path/to/output
25+
26+
## Example
27+
28+
Extract [test/fixtures/en.wikipedia.org.har](test/fixtures/en.wikipedia.org.har) file to directory.
29+
30+
```
31+
npx har-extractor ./test/fixtures/en.wikipedia.org.har -o wikipedia
32+
wikipedia/en.wikipedia.org/wiki/har
33+
wikipedia/en.wikipedia.org/static/images/project-logos/enwiki-2x.png
34+
wikipedia/en.wikipedia.org/w/load.php!debug=false&lang=en&modules=ext.cite.styles!ext.uls.interlanguage!ext.visualEditor.desktopA
35+
wikipedia/en.wikipedia.org/w/load.php!debug=false&lang=en&modules=startup&only=scripts&skin=vector
36+
wikipedia/en.wikipedia.org/w/load.php!debug=false&lang=en&modules=ext.gadget.charinsert-styles&only=styles&skin=vector
37+
wikipedia/en.wikipedia.org/w/load.php!debug=false&lang=en&modules=site.styles&only=styles&skin=vector
38+
wikipedia/en.wikipedia.org/static/images/wikimedia-button-2x.png
39+
wikipedia/en.wikipedia.org/static/images/poweredby_mediawiki_176x62.png
40+
wikipedia/en.wikipedia.org/w/load.php!debug=false&lang=en&modules=jquery,mediawiki!mediawiki.legacy.wikibits&only=scripts&skin=ve
41+
wikipedia/en.wikipedia.org/static/images/mobile/copyright/wikipedia-wordmark-en.svg
42+
```
43+
44+
45+
## Changelog
46+
47+
See [Releases page](https://github.com/azu/har-extractor/releases).
48+
49+
## Running tests
50+
51+
Install devDependencies and Run `npm test`:
52+
53+
npm i -d && npm test
54+
55+
## Contributing
56+
57+
Pull requests and stars are always welcome.
58+
59+
For bugs and feature requests, [please create an issue](https://github.com/azu/har-extractor/issues).
60+
61+
1. Fork it!
62+
2. Create your feature branch: `git checkout -b my-new-feature`
63+
3. Commit your changes: `git commit -am 'Add some feature'`
64+
4. Push to the branch: `git push origin my-new-feature`
65+
5. Submit a pull request :D
66+
67+
## Author
68+
69+
- [github/azu](https://github.com/azu)
70+
- [twitter/azu_re](https://twitter.com/azu_re)
71+
72+
## License
73+
74+
MIT © azu

bin/cmd.js

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env node
2+
"use strict";
3+
const fs = require("fs");
4+
const path = require("path");
5+
const meow = require("meow");
6+
const { extract } = require("../lib/har-extractor.js");
7+
const cli = meow(
8+
`
9+
Usage
10+
$ har-extractor <harfile> --output /path/to/output
11+
12+
Options:
13+
--output, -o Output directory
14+
--dry-run Enable dry run mode
15+
--verbose Show processing file path
16+
17+
Examples
18+
$ har-extractor ./net.har --output /path/to/output
19+
`,
20+
{
21+
flags: {
22+
output: {
23+
type: "string",
24+
alias: "o"
25+
},
26+
verbose: {
27+
type: "boolean",
28+
default: true
29+
},
30+
dryRun: {
31+
type: "boolean",
32+
default: false
33+
}
34+
},
35+
autoHelp: true
36+
}
37+
);
38+
39+
const harFilePath = cli.input[0];
40+
if (!harFilePath) {
41+
cli.showHelp();
42+
}
43+
try {
44+
const harContent = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), harFilePath), "utf-8"));
45+
extract(harContent, {
46+
verbose: cli.flags.verbose,
47+
dryRun: cli.flags.dryRun,
48+
outputDir: cli.flags.output
49+
});
50+
} catch (error) {
51+
console.error(error);
52+
cli.showHelp();
53+
}

package.json

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{
2+
"name": "har-extractor",
3+
"version": "1.0.0",
4+
"description": "A CLI that extract har file to directory.",
5+
"keywords": [
6+
"archieve",
7+
"directory",
8+
"extract",
9+
"file",
10+
"folder",
11+
"har",
12+
"unzip"
13+
],
14+
"homepage": "https://github.com/azu/har-extractor",
15+
"bugs": {
16+
"url": "https://github.com/azu/har-extractor/issues"
17+
},
18+
"license": "MIT",
19+
"author": "azu",
20+
"files": [
21+
"bin/",
22+
"lib/",
23+
"src/"
24+
],
25+
"main": "lib/har-extractor.js",
26+
"types": "lib/har-extractor.d.ts",
27+
"bin": {
28+
"har-extractor": "./bin/cmd.js"
29+
},
30+
"directories": {
31+
"lib": "lib",
32+
"test": "test"
33+
},
34+
"repository": {
35+
"type": "git",
36+
"url": "https://github.com/azu/har-extractor.git"
37+
},
38+
"scripts": {
39+
"build": "cross-env NODE_ENV=production tsc -p .",
40+
"clean": "rimraf lib/",
41+
"precommit": "lint-staged",
42+
"postcommit": "git reset",
43+
"prepublish": "npm run --if-present build",
44+
"test": "mocha \"test/**/*.ts\"",
45+
"prettier": "prettier --write \"**/*.{js,jsx,ts,tsx,css}\"",
46+
"watch": "tsc -p . --watch"
47+
},
48+
"prettier": {
49+
"printWidth": 120,
50+
"singleQuote": false,
51+
"tabWidth": 4
52+
},
53+
"devDependencies": {
54+
"@types/har-format": "^1.2.3",
55+
"@types/mocha": "^5.2.2",
56+
"@types/node": "^10.3.4",
57+
"cross-env": "^5.2.0",
58+
"del": "^3.0.0",
59+
"glob": "^7.1.2",
60+
"husky": "^0.14.3",
61+
"lint-staged": "^7.2.0",
62+
"mocha": "^5.2.0",
63+
"prettier": "^1.13.5",
64+
"rimraf": "^2.6.2",
65+
"ts-node": "^6.1.1",
66+
"ts-node-test-register": "^3.0.0",
67+
"typescript": "^2.9.2"
68+
},
69+
"lint-staged": {
70+
"*.{js,jsx,ts,tsx,css}": [
71+
"prettier --write",
72+
"git add"
73+
]
74+
},
75+
"dependencies": {
76+
"filenamify": "^2.1.0",
77+
"humanize-url": "^1.0.1",
78+
"make-dir": "^1.3.0",
79+
"meow": "^5.0.0"
80+
}
81+
}

src/har-extractor.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import * as fs from "fs";
2+
import { Har, Entry } from "har-format";
3+
import * as path from "path";
4+
5+
const filenamify = require("filenamify");
6+
const humanizeUrl = require("humanize-url");
7+
const makeDir = require("make-dir");
8+
export const getEntryContentAsBuffer = (entry: Entry): Buffer | undefined => {
9+
const content = entry.response.content;
10+
const text = content.text;
11+
if (text === undefined) {
12+
return;
13+
}
14+
if (content.encoding === "base64") {
15+
return Buffer.from(text, "base64");
16+
} else {
17+
return Buffer.from(text);
18+
}
19+
};
20+
21+
export const convertEntryAsFilePathFormat = (entry: Entry): string => {
22+
const requestURL = entry.request.url;
23+
const stripSchemaURL: string = humanizeUrl(requestURL);
24+
const dirnames: string[] = stripSchemaURL.split("/").map(pathname => {
25+
return filenamify(pathname);
26+
});
27+
return dirnames.join("/");
28+
};
29+
30+
export interface ExtractOptions {
31+
outputDir: string;
32+
verbose?: boolean;
33+
dryRun?: boolean;
34+
}
35+
36+
export const extract = (harContent: Har, options: ExtractOptions) => {
37+
harContent.log.entries.forEach(entry => {
38+
const buffer = getEntryContentAsBuffer(entry);
39+
if (!buffer) {
40+
return;
41+
}
42+
const outputPath = path.join(options.outputDir, convertEntryAsFilePathFormat(entry));
43+
makeDir.sync(path.dirname(outputPath));
44+
if (options.verbose) {
45+
console.log(outputPath);
46+
}
47+
if (!options.dryRun) {
48+
fs.writeFileSync(outputPath, buffer);
49+
}
50+
});
51+
};

0 commit comments

Comments
 (0)