diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..dde7877 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# http://editorconfig.org +root = true + +[*] +end_of_line = lf +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true + +[{*.js,*.mjs,*.ts,*.json,*.yml}] +indent_size = 2 +indent_style = space diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +node_modules/ diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..8163cb0 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,272 @@ +{ + "env": { + "browser": true, + "es6": true, + "node": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "ecmaVersion": "latest" + }, + "globals": { + "BigInt": true + }, + "rules": { + "indent": [ + "error", + 2 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ], + "no-loop-func": [ + "error" + ], + "block-spacing": [ + "error", + "always" + ], + "camelcase": [ + "error" + ], + "eqeqeq": [ + "error", + "always" + ], + "strict": [ + "error", + "global" + ], + "brace-style": [ + "error", + "1tbs", + { + "allowSingleLine": true + } + ], + "comma-style": [ + "error", + "last" + ], + "comma-spacing": [ + "error", + { + "before": false, + "after": true + } + ], + "eol-last": [ + "error" + ], + "func-call-spacing": [ + "error", + "never" + ], + "key-spacing": [ + "error", + { + "beforeColon": false, + "afterColon": true, + "mode": "minimum" + } + ], + "keyword-spacing": [ + "error", + { + "before": true, + "after": true, + "overrides": { + "function": { + "after": false + } + } + } + ], + "max-len": [ + "error", + { + "code": 80, + "ignoreUrls": true + } + ], + "max-nested-callbacks": [ + "error", + { + "max": 7 + } + ], + "new-cap": [ + "error", + { + "newIsCap": true, + "capIsNew": false, + "properties": true + } + ], + "new-parens": [ + "error" + ], + "no-lonely-if": [ + "error" + ], + "no-trailing-spaces": [ + "error" + ], + "no-unneeded-ternary": [ + "error" + ], + "no-whitespace-before-property": [ + "error" + ], + "object-curly-spacing": [ + "error", + "always" + ], + "operator-assignment": [ + "error", + "always" + ], + "operator-linebreak": [ + "error", + "after" + ], + "semi-spacing": [ + "error", + { + "before": false, + "after": true + } + ], + "space-before-blocks": [ + "error", + "always" + ], + "space-before-function-paren": [ + "error", + { + "anonymous": "never", + "named": "never", + "asyncArrow": "always" + } + ], + "space-in-parens": [ + "error", + "never" + ], + "space-infix-ops": [ + "error" + ], + "space-unary-ops": [ + "error", + { + "words": true, + "nonwords": false, + "overrides": { + "typeof": false + } + } + ], + "no-unreachable": [ + "error" + ], + "no-global-assign": [ + "error" + ], + "no-self-compare": [ + "error" + ], + "no-unmodified-loop-condition": [ + "error" + ], + "no-constant-condition": [ + "error", + { + "checkLoops": false + } + ], + "no-console": [ + "off" + ], + "no-useless-concat": [ + "error" + ], + "no-useless-escape": [ + "error" + ], + "no-shadow-restricted-names": [ + "error" + ], + "no-use-before-define": [ + "error", + { + "functions": false + } + ], + "arrow-parens": [ + "error", + "always" + ], + "arrow-body-style": [ + "error", + "as-needed" + ], + "arrow-spacing": [ + "error" + ], + "no-confusing-arrow": [ + "error", + { + "allowParens": true + } + ], + "no-useless-computed-key": [ + "error" + ], + "no-useless-rename": [ + "error" + ], + "no-var": [ + "error" + ], + "object-shorthand": [ + "error", + "always" + ], + "prefer-arrow-callback": [ + "error" + ], + "prefer-const": [ + "error" + ], + "prefer-numeric-literals": [ + "error" + ], + "prefer-rest-params": [ + "error" + ], + "prefer-spread": [ + "error" + ], + "rest-spread-spacing": [ + "error", + "never" + ], + "template-curly-spacing": [ + "error", + "never" + ], + "consistent-return": [ + "error", + { "treatUndefinedAsUnspecified": true } + ] + } +} diff --git a/.eslintrc.yml b/.eslintrc.yml deleted file mode 100644 index de3adce..0000000 --- a/.eslintrc.yml +++ /dev/null @@ -1,173 +0,0 @@ -env: - es6: true - node: true -extends: 'eslint:recommended' -globals: - api: false -rules: - indent: - - error - - 2 - - SwitchCase: 1 - VariableDeclarator: - var: 2 - let: 2 - const: 3 - MemberExpression: 1 - linebreak-style: - - error - - unix - quotes: - - error - - single - semi: - - error - - always - eqeqeq: - - error - - always - no-loop-func: - - error - strict: - - error - - global - block-spacing: - - error - - always - brace-style: - - error - - 1tbs - - allowSingleLine: true - camelcase: - - error - comma-style: - - error - - last - comma-spacing: - - error - - before: false - after: true - eol-last: - - error - func-call-spacing: - - error - - never - key-spacing: - - error - - beforeColon: false - afterColon: true - mode: minimum - keyword-spacing: - - error - - before: true - after: true - overrides: - function: - after: false - max-len: - - error - - code: 80 - ignoreUrls: true - max-nested-callbacks: - - error - - max: 7 - new-cap: - - error - - newIsCap: true - capIsNew: true - properties: true - new-parens: - - error - no-lonely-if: - - error - no-trailing-spaces: - - error - no-unneeded-ternary: - - error - no-whitespace-before-property: - - error - object-curly-spacing: - - error - - always - operator-assignment: - - error - - always - operator-linebreak: - - error - - after - semi-spacing: - - error - - before: false - after: true - space-before-blocks: - - error - - always - space-before-function-paren: - - error - - never - space-in-parens: - - error - - never - space-infix-ops: - - error - space-unary-ops: - - error - - words: true - nonwords: false - overrides: - typeof: false - no-unreachable: - - error - no-global-assign: - - error - no-self-compare: - - error - no-unmodified-loop-condition: - - error - no-constant-condition: - - error - - checkLoops: false - no-console: - - off - no-useless-concat: - - error - no-useless-escape: - - error - no-shadow-restricted-names: - - error - no-use-before-define: - - error - - functions: false - arrow-body-style: - - error - - as-needed - arrow-spacing: - - error - no-confusing-arrow: - - error - - allowParens: true - no-useless-computed-key: - - error - no-useless-rename: - - error - no-var: - - error - object-shorthand: - - error - - always - prefer-arrow-callback: - - error - prefer-const: - - error - prefer-numeric-literals: - - error - prefer-rest-params: - - error - prefer-spread: - - error - rest-spread-spacing: - - error - - never - template-curly-spacing: - - error - - never diff --git a/JavaScript/1-get.js b/JavaScript/1-get.js index f40e2bb..3f3ac0a 100644 --- a/JavaScript/1-get.js +++ b/JavaScript/1-get.js @@ -1,20 +1,23 @@ 'use strict'; -const http = require('http'); +const http = require('node:http'); const url = 'http://ietf.org/'; -http.get(url, res => { +http.get(url, (res) => { + console.log(res.req._header); + console.dir(res.headers); if (res.statusCode !== 200) { - console.log(`Status Code: ${res.statusCode}`); + const { statusCode, statusMessage } = res; + console.log(`Status Code: ${statusCode} ${statusMessage}`); return; } res.setEncoding('utf8'); - const lines = []; - res.on('data', chunk => { - lines.push(chunk); + const buffer = []; + res.on('data', (chunk) => { + buffer.push(chunk); }); res.on('end', () => { - console.log(lines.join()); + console.log(buffer.join()); }); }); diff --git a/JavaScript/2-fetch.js b/JavaScript/2-fetch.js deleted file mode 100644 index d77757a..0000000 --- a/JavaScript/2-fetch.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -const http = require('http'); - -const fetch = url => new Promise((resolve, reject) => http.get(url, res => { - if (res.statusCode !== 200) { - reject(`Status Code: ${res.statusCode}`); - return; - } - res.setEncoding('utf8'); - const lines = []; - res.on('data', chunk => lines.push(chunk)); - res.on('end', () => resolve(lines.join())); -})); - -// Usage - -fetch('http://ietf.org/') - .then(body => console.log(body)) - .catch(err => console.error(err)); diff --git a/JavaScript/2-get-https.js b/JavaScript/2-get-https.js new file mode 100644 index 0000000..95f0679 --- /dev/null +++ b/JavaScript/2-get-https.js @@ -0,0 +1,28 @@ +'use strict'; + +const https = require('node:https'); +const fs = require('node:fs'); + +const url = 'https://ietf.org/'; + +https.get(url, (res) => { + console.log(res.req._header); + console.dir(res.headers); + if (res.statusCode !== 200) { + const { statusCode, statusMessage } = res; + console.log(`Status Code: ${statusCode} ${statusMessage}`); + return; + } + res.setEncoding('utf8'); + const buffer = []; + res.on('data', (chunk) => { + buffer.push(chunk); + }); + res.on('end', () => { + const data = buffer.join(); + console.log({ size: data.length, chunks: buffer.length }); + fs.writeFile('content.html', data, () => { + console.log('Saved to file: content.html'); + }); + }); +}); diff --git a/JavaScript/3-fetch.js b/JavaScript/3-fetch.js new file mode 100644 index 0000000..0309c78 --- /dev/null +++ b/JavaScript/3-fetch.js @@ -0,0 +1,24 @@ +'use strict'; + +const http = require('node:http'); +const https = require('node:https'); + +const fetch = (url) => new Promise((resolve, reject) => { + const protocol = url.startsWith('https') ? https : http; + protocol.get(url, (res) => { + if (res.statusCode !== 200) { + const { statusCode, statusMessage } = res; + reject(new Error(`Status Code: ${statusCode} ${statusMessage}`)); + } + res.setEncoding('utf8'); + const buffer = []; + res.on('data', (chunk) => buffer.push(chunk)); + res.on('end', () => resolve(buffer.join())); + }); +}); + +// Usage + +fetch('http://ietf.org/') + .then((body) => console.log(body)) + .catch((err) => console.error(err)); diff --git a/JavaScript/3-xhr.html b/JavaScript/4-xhr.html similarity index 74% rename from JavaScript/3-xhr.html rename to JavaScript/4-xhr.html index 5c46fdc..25c8abb 100644 --- a/JavaScript/3-xhr.html +++ b/JavaScript/4-xhr.html @@ -9,9 +9,8 @@ const xhr = new XMLHttpRequest(); xhr.onreadystatechange = () => { if (xhr.readyState === XMLHttpRequest.DONE) { - message.innerHTML = (xhr.status === 200 ? - xhr.responseText : 'Error code: ' + xhr.status - ); + message.innerHTML = xhr.status === 200 ? + xhr.responseText : `Error code: ${xhr.status}`; } }; xhr.open('GET', '/person', true); diff --git a/JavaScript/3-xhr.js b/JavaScript/4-xhr.js similarity index 61% rename from JavaScript/3-xhr.js rename to JavaScript/4-xhr.js index 13ca2f9..eddfbe5 100644 --- a/JavaScript/3-xhr.js +++ b/JavaScript/4-xhr.js @@ -1,9 +1,9 @@ 'use strict'; -const fs = require('fs'); -const http = require('http'); +const fs = require('node:fs'); +const http = require('node:http'); -const index = fs.readFileSync('./3-xhr.html'); +const index = fs.readFileSync('./4-xhr.html'); http.createServer((req, res) => { if (req.url === '/person') { diff --git a/JavaScript/4-fetch.html b/JavaScript/5-fetch.html similarity index 100% rename from JavaScript/4-fetch.html rename to JavaScript/5-fetch.html diff --git a/JavaScript/4-fetch.js b/JavaScript/5-fetch.js similarity index 62% rename from JavaScript/4-fetch.js rename to JavaScript/5-fetch.js index 472585f..edee09a 100644 --- a/JavaScript/4-fetch.js +++ b/JavaScript/5-fetch.js @@ -1,9 +1,9 @@ 'use strict'; -const fs = require('fs'); -const http = require('http'); +const fs = require('node:fs'); +const http = require('node:http'); -const index = fs.readFileSync('./4-fetch.html'); +const index = fs.readFileSync('./5-fetch.html'); const person = { name: 'Marcus' }; const data = JSON.stringify(person); diff --git a/JavaScript/5-api.js b/JavaScript/6-api.js similarity index 75% rename from JavaScript/5-api.js rename to JavaScript/6-api.js index a8fb98d..afbf251 100644 --- a/JavaScript/5-api.js +++ b/JavaScript/6-api.js @@ -1,6 +1,6 @@ 'use strict'; -const http = require('http'); +const http = require('node:http'); const ajax = (base, methods) => { const api = {}; @@ -9,14 +9,14 @@ const ajax = (base, methods) => { const callback = args.pop(); const url = base + method + '/' + args.join('/'); console.log(url); - http.get(url, res => { + http.get(url, (res) => { if (res.statusCode !== 200) { callback(new Error(`Status Code: ${res.statusCode}`)); return; } - const lines = []; - res.on('data', chunk => lines.push(chunk)); - res.on('end', () => callback(null, JSON.parse(lines.join()))); + const buffer = []; + res.on('data', (chunk) => buffer.push(chunk)); + res.on('end', () => callback(null, JSON.parse(buffer.join()))); }); }; } diff --git a/JavaScript/5-server.js b/JavaScript/6-server.js similarity index 78% rename from JavaScript/5-server.js rename to JavaScript/6-server.js index d033718..70a5275 100644 --- a/JavaScript/5-server.js +++ b/JavaScript/6-server.js @@ -1,6 +1,6 @@ 'use strict'; -const http = require('http'); +const http = require('node:http'); const users = { marcus: { name: 'Marcus Aurelius', city: 'Rome', born: 121 }, @@ -8,8 +8,8 @@ const users = { }; const routing = { - '/api/user': name => users[name], - '/api/userBorn': name => users[name].born + '/api/user': (name) => users[name], + '/api/userBorn': (name) => users[name].born }; http.createServer((req, res) => { diff --git a/LICENSE b/LICENSE index 8864d4a..f24dbdd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 +Copyright (c) 2017-2022 How.Programming.Works contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 4a28245..dd7d024 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# HTTP Request, XMLHttpRequest, fetch +## HTTP Request, XMLHttpRequest, fetch + +[![HTTP запросы в бреузере и Node.js: XMLHttpRequest, fetch](https://img.youtube.com/vi/wMMki2FEYGY/0.jpg)](https://www.youtube.com/watch?v=wMMki2FEYGY)