{"id":15677077,"url":"https://github.com/nwtgck/rich-piping-server","last_synced_at":"2025-05-07T00:45:11.442Z","repository":{"id":37020034,"uuid":"237432974","full_name":"nwtgck/rich-piping-server","owner":"nwtgck","description":"Rich Piping Server","archived":false,"fork":false,"pushed_at":"2024-04-20T11:25:01.000Z","size":702,"stargazers_count":13,"open_issues_count":7,"forks_count":1,"subscribers_count":3,"default_branch":"develop","last_synced_at":"2024-04-20T13:55:20.200Z","etag":null,"topics":["basic-authentication","openid-connect","piping-server"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nwtgck.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2020-01-31T13:13:15.000Z","updated_at":"2024-04-23T14:04:22.466Z","dependencies_parsed_at":"2023-01-17T13:45:29.637Z","dependency_job_id":"21511f43-94bf-41ac-a30c-ea71f1e4f0e4","html_url":"https://github.com/nwtgck/rich-piping-server","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nwtgck%2Frich-piping-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nwtgck%2Frich-piping-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nwtgck%2Frich-piping-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nwtgck%2Frich-piping-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nwtgck","download_url":"https://codeload.github.com/nwtgck/rich-piping-server/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252793563,"owners_count":21805054,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["basic-authentication","openid-connect","piping-server"],"created_at":"2024-10-03T16:08:21.706Z","updated_at":"2025-05-07T00:45:11.422Z","avatar_url":"https://github.com/nwtgck.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rich-piping-server\n![Node CI](https://github.com/nwtgck/rich-piping-server/workflows/Node%20CI/badge.svg)\n\nRich [Piping Server](https://github.com/nwtgck/piping-server)\n\n## Usage\n\nPrepare `config.yaml` as follows.\n\n```yaml\nversion: '1'\nconfig_for: rich_piping_server\n\n# optional\nbasic_auth_users:\n  - username: user1\n    password: pass1234\n\n# optional\nallow_paths:\n  # Allow transfer over \"/0s6twklxkrcfs1u\", not \"/0s6twklxkrcfs1u/mypath\"\n  - /0s6twklxkrcfs1u\n  # Allow transfer over the regular expression below\n  - regexp: ^/[abcd]+.*$\n  # Simple at /mytop1/. Show version at /mytop1/version. Show help at /mytop1/help. Allow transfer /mytop1/mypath, /mytop1/hoge,....\n  - index: /mytop1\n  # Create multiple \"index\".\n  - index: /mytop2\n\n# Respond a fake nginx 500 down page when path not allowed\nrejection: fake_nginx_down\n\n# Close socket when path not allowed\n#rejection: socket_close\n\n# Respond a fake nginx 500 down with version\n#rejection:\n#  fake_nginx_down:\n#    nginx_version: 99.9.9\n```\n\nRun the server as follows. Hot reload of config is available.\n\n```bash\nnpx nwtgck/rich-piping-server --config-path=config.yaml\n```\n\nHere are some example results of the server with the config.\n\n- transferable: `curl -u user1:pass1234 http://localhost:8080/0s6twklxkrcfs1u`\n- transferable: `curl -u user1:pass1234 -T- http://localhost:8080/0s6twklxkrcfs1u`\n- transferable: `curl -u user1:pass1234 http://localhost:8080/aabbaaccba`\n- transferable: `curl -u user1:pass1234 http://localhost:8080/b`\n- Web UI because of \"index\": `curl -u user1:pass1234 http://localhost:8080/mytop1/`\n- version because of \"index\": `curl -u user1:pass1234 http://localhost:8080/mytop1/version`\n- help because of \"index\": `curl -u user1:pass1234 http://localhost:8080/mytop1/help`\n- transferable because of \"index\": `curl -u user1:pass1234 http://localhost:8080/mytop1/mypath`\n- Web UI because of \"index\": `curl -u user1:pass1234 http://localhost:8080/mytop2/`\n- reject because path is not allowed: `curl -u user1:pass1234 http://localhost:8080/`\n- reject because of no basic auth: `curl http://localhost:8080/0s6twklxkrcfs1u`\n\n### Tags\n\nThese tags are available in config.\n- `!env MY_VALUE1`\n- `!concat [ \"hello\", !env \"MY_VALUE1\" ]`\n- `!json_decode \"true\"`\n- `!unrecommended_js \"return new Date().getMonth() \u003c 5\"`\n\nHere is an example.\n\n```yaml\n...\n\nbasic_auth_users:\n  - username: !env \"USERNAME1\"\n    password: !env \"PASSWORD1\"\n...\n```\n\n`!unrecommended_js` is not recommended to use because this behavior highly depends on the underlying runtime and the behavior may change. \n\n### OpenID Connect\n\nThis is an experimental feature and it may have **breaking changes without config version update**.\n\n```yaml\nversion: '1'\nconfig_for: rich_piping_server\n\n# OpenID Connect is experimental\nexperimental_openid_connect: true\n\n# optional\nopenid_connect:\n  issuer_url: https://example.us.auth0.com\n  client_id: !env \"OIDC_CLIENT_ID\"\n  client_secret: !env \"OIDC_CLIENT_SECRET\"\n  redirect:\n    # Rich Piping Server callback URL\n    uri: https://my.rich.piping.server/callback\n    path: /callback\n  allow_userinfos:\n    - sub: auth0|0123456789abcdef01234567\n    - email: johnsmith@example.com\n    - email: alice@example.com\n      require_verification: false\n  # Session ID is generated after authentication successful and user in \"allow_userinfos\"\n  # Shutting down Rich Piping Server revokes all sessions for now\n  session:\n    cookie:\n      name: my_session_id\n      http_only: true\n    # optional (useful especially for command line tools to get session ID)\n    forward:\n      # A CLI may server an ephemeral HTTP server on :65106 and open https://my.rich.piping.server/?my_session_forward_url=http://localhost:65106\n      # The opened browser will POST http://localhost:65106 with `{ \"session_id\": \"...\" }` after logged in.\n      query_param_name: my_session_forward_url\n      allow_url_regexp: ^http://localhost:\\d+.*$\n    # optional\n    custom_http_header: X-My-Session-ID\n    age_seconds: 86400\n  # optional\n  log:\n    # optional\n    userinfo:\n      sub: false\n      email: false\n\n# Close socket when path not allowed\nrejection: socket_close\n```\n\n#### What is session forwarding for?\n\nThe config has `.openid_connect.session.forward`. It is useful for CLI to get session ID.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample CLI to get session ID in Node.js\u003c/summary\u003e\n\n```js\nconst http = require(\"http\");\n\n(async () =\u003e {\n  const richPipingServerUrl = \"https://my.rich.piping.server\";\n  const sessionId = await getSessionId(richPipingServerUrl);\n  console.log(\"sessionId:\", sessionId);\n  // (you can use session ID now save to ~/.config/... or something)\n\n  // Example to access the Rich Piping Server\n  const res = await fetch(`${richPipingServerUrl}/version`, {\n    headers: { \"Cookie\": `my_session_id=${sessionId}` }\n  });\n  console.log(\"Underlying Piping Server version:\", await res.text());\n})();\n\n// Open default browser and get session ID\nfunction getSessionId(richPipingServerUrl) {\n  return new Promise((resolve, reject) =\u003e {\n    const server = http.createServer((req, res) =\u003e {\n      if (req.method === \"OPTIONS\") {\n        res.writeHead(200, {\n          \"Access-Control-Allow-Origin\": \"*\",\n          \"Access-Control-Allow-Methods\": \"GET, POST, OPTIONS\",\n          \"Access-Control-Allow-Headers\": \"Content-Type\",\n          // Private Network Access preflights: https://developer.chrome.com/blog/private-network-access-preflight/\n          ...(req.headers[\"access-control-request-private-network\"] === \"true\" ? {\n            \"Access-Control-Allow-Private-Network\": \"true\",\n          }: {}),\n          \"Access-Control-Max-Age\": 86400,\n          \"Content-Length\": 0\n        });\n        res.end();\n        return;\n      }\n      if (req.method === \"POST\") {\n        let body = \"\";\n        req.on('data', (chunk) =\u003e {\n          body += chunk;\n        });\n        req.on('end', () =\u003e {\n          res.writeHead(200, {\n            \"Access-Control-Allow-Origin\": \"*\",\n          });\n          res.end();\n          try {\n            const sessionId = JSON.parse(body).session_id;\n            resolve(sessionId);\n          } catch (err) {\n            reject(err);\n          }\n          server.close();\n        });\n        req.on(\"error\", (err) =\u003e {\n          server.close();\n          reject(err);\n        });\n      }\n    });\n    server.listen(0, () =\u003e {\n      // This ephemeral server is session forward URL\n      const sessionForwardUrl = `http://localhost:${server.address().port}`;\n      const serverUrl = new URL(richPipingServerUrl);\n      serverUrl.searchParams.set(\"my_session_forward_url\", sessionForwardUrl);\n      // Open the browser\n      // NOTE: This is only for macOS. Use other command for Windows, Linux\n      require(\"child_process\").execSync(`open ${serverUrl.href}`);\n      // Use `npm install open` and `open(serverUrl.href)`\n    });\n  });\n}\n```\n\u003c/details\u003e\n\n### Run on Docker\n\nPrepare `./config.yaml` and run as follows on Docker.\n\n```bash\ndocker run -p 8181:8080 -v $PWD/config.yaml:/config.yaml nwtgck/rich-piping-server --config-path=/config.yaml\n```\n\nThe server runs on \u003chttp://localhost:8181\u003e.\n\n## Config examples\n\nConfig examples are found in the tests:  \n\u003chttps://github.com/nwtgck/rich-piping-server/blob/a2cd491220658561a1509f5a7a8321144c1a3ac7/test/config-v1.test.ts#L42-L459\u003e\n\n## Migration from legacy config\n\nThe command below prints new config.\n\n```bash\nrich-piping-server --config-path=./config.yaml migrate-config\n```\n\nNew Rich Piping Server supports the legacy config schema without migration.\n\n## Options\n\n```\nrich-piping-server [command]\n\nCommands:\n  rich-piping-server migrate-config  Print migrated config\n\nOptions:\n  --help                             Show help                         [boolean]\n  --version                          Show version number               [boolean]\n  --host                             Bind address (e.g. 127.0.0.1, ::1) [string]\n  --http-port                        Port of HTTP server         [default: 8080]\n  --enable-https                     Enable HTTPS     [boolean] [default: false]\n  --https-port                       Port of HTTPS server               [number]\n  --key-path                         Private key path                   [string]\n  --crt-path                         Certification path                 [string]\n  --env-path                         .env file path                     [string]\n  --config-path, --config-yaml-path  Config YAML path        [string] [required]\n  --debug-config                     Print normalized config as JSON (all env!\n                                     and other tangs are evaluated)\n                                                      [boolean] [default: false]\n\nExample configs are found in\nhttps://github.com/nwtgck/rich-piping-server#readme\n```\n\n## Relation to Piping Server\nRich Piping Server uses internally Piping Server as a library:  \n\u003chttps://github.com/nwtgck/rich-piping-server/blob/7e687bfef0228eea4879c968729b31c0d839347b/src/rich-piping-server.ts#L3\u003e\n\nTransfer logic is completely the same as the original Piping Server.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnwtgck%2Frich-piping-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnwtgck%2Frich-piping-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnwtgck%2Frich-piping-server/lists"}