{"id":13492405,"url":"https://github.com/nicholaschiasson/ngx_upstream_jdomain","last_synced_at":"2025-04-05T06:04:17.167Z","repository":{"id":39651445,"uuid":"202216584","full_name":"nicholaschiasson/ngx_upstream_jdomain","owner":"nicholaschiasson","description":"An asynchronous domain name resolution module for nginx upstream.","archived":false,"fork":false,"pushed_at":"2024-12-09T17:42:58.000Z","size":212,"stargazers_count":105,"open_issues_count":12,"forks_count":33,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-29T05:04:36.070Z","etag":null,"topics":["c","dns","dns-lookup","dns-resolution","hacktoberfest","http","nginx","resolver","server","task-runner","upstream","upstreams"],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nicholaschiasson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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,"publiccode":null,"codemeta":null},"funding":{"github":"nicholaschiasson","patreon":null,"open_collective":"nicholaschiasson","ko_fi":"nicholaschiasson","tidelift":null,"community_bridge":null,"liberapay":"nicholaschiasson","issuehunt":"nicholaschiasson","otechie":null,"custom":["buymeacoffee.com/nickyc"]}},"created_at":"2019-08-13T20:09:55.000Z","updated_at":"2025-03-12T04:13:44.000Z","dependencies_parsed_at":"2024-01-16T09:05:55.881Z","dependency_job_id":"974737ff-c9ed-4a2c-9623-3eeebc01f052","html_url":"https://github.com/nicholaschiasson/ngx_upstream_jdomain","commit_stats":{"total_commits":231,"total_committers":11,"mean_commits":21.0,"dds":"0.18181818181818177","last_synced_commit":"801406f76e47e3d5d5cfdcbd6feada500ebd62ce"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicholaschiasson%2Fngx_upstream_jdomain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicholaschiasson%2Fngx_upstream_jdomain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicholaschiasson%2Fngx_upstream_jdomain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicholaschiasson%2Fngx_upstream_jdomain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nicholaschiasson","download_url":"https://codeload.github.com/nicholaschiasson/ngx_upstream_jdomain/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247294516,"owners_count":20915340,"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":["c","dns","dns-lookup","dns-resolution","hacktoberfest","http","nginx","resolver","server","task-runner","upstream","upstreams"],"created_at":"2024-07-31T19:01:05.700Z","updated_at":"2025-04-05T06:04:17.146Z","avatar_url":"https://github.com/nicholaschiasson.png","language":"Perl","funding_links":["https://github.com/sponsors/nicholaschiasson","https://opencollective.com/nicholaschiasson","https://ko-fi.com/nicholaschiasson","https://liberapay.com/nicholaschiasson","https://issuehunt.io/r/nicholaschiasson","buymeacoffee.com/nickyc"],"categories":["Perl","Upstreams, rate limiting and access control"],"sub_categories":[],"readme":"# ngx_upstream_jdomain\n\nAn asynchronous domain name resolution module for nginx upstream.\n\nThis module allows you to use a domain name in an upstream block and expect the\ndomain name to be dynamically resolved so your upstream may be resilient to DNS\nentry updates.\n\nThe module does not perform DNS resolution automatically on some interval.\nInstead, the DNS resolution needs to be prompted by a request for the given\nupstream. If nginx serves a connection bound for a jdomain upstream, and the\nconfigured `interval` has elapsed, then the module will perform a DNS lookup.\n\nThe module is compatible with other `upstream` scope directives. This means you\nmay populate an `upstream` block with multiple `jdomain` directives, multiple\n`server` directives, `keepalive`, load balancing directives, etc. Note that\nunless another load balancing method is specified in the `upstream` block, this\nmodule makes use of the default round robin load balancing algorithm built into\nnginx core.\n\n**Important Note**: Should an alternate load balancing algorithm be specified,\n**it must come _before_ the jdomain directive in the upstream block!** If this\nis not followed, nginx **_will_** crash during runtime! This is because many\nother load balancing modules explicitly extend the built in round robin, and\nthus end up clobbering the jdomain initialization handlers, since jdomain is\ntechnically a load balancer module as well. While this may not be the case with\nall load balancer modules, it's better to stay on the safe side and place\njdomain after.\n\n**Important Note**: Due to the non blocking nature of this module and the fact\nthat its DNS resolution is triggered by incoming requests, the request that\nprompts a lookup will actually still be forwarded to the upstream that was\nresolved and cached before the DNS lookup happens. Depending on the scenario,\nthis could result in a one off failure when changing the states of\nupstreams. This is important to keep in mind to ensure graceful transitions of\nyour upstreams.\n\nThis repository is a fork of [a repository](https://github.com/wdaike/ngx_upstream_jdomain)\noriginally authored by [wdaike](https://github.com/wdaike). As that project is\nno longer maintained, this repository aims to be its successor and is now\nseveral features ahead.\n\n## Installation\n\n[Build nginx](http://nginx.org/en/docs/configure.html) with this repository as\na static or dynamic module.\n\n```shell\n./configure --add-module=/path/to/this/directory\nmake\nmake install\n```\n\n## Usage\n\n```nginx\nresolver 8.8.8.8; # Your Local DNS Server\n\n# Basic upstream using domain name defaulting to port 80.\nupstream backend_01 {\n\tjdomain example.com;\n}\n\n# Basic upstream specifying different port.\nupstream backend_02 {\n\tjdomain example.com port=8080;\n}\n\n# Upstream with a backup server to use in case of host not found or format\n# errors on DNS resolution.\nupstream backend_03 {\n\tserver 127.0.0.2 backup;\n\tjdomain example.com;\n}\n\n# Upstream which will use backup for any and all DNS resolution errors.\nupstream backend_04 {\n\tserver 127.0.0.2 backup;\n\tjdomain example.com strict;\n}\n\nserver {\n\tlisten 127.0.0.2:80;\n\treturn 502 'An error.';\n}\n```\n\n## Synopsis\n\n```\nSyntax: jdomain \u003cdomain-name\u003e [port=80] [max_ips=4] [interval=1] [strict]\nContext: upstream\nAttributes:\n\tport:       Backend's listening port.                                      (Default: 80)\n\tmax_ips:    IP buffer size. Maximum number of resolved IPs to cache.       (Default: 4)\n\tinterval:   How many seconds to resolve domain name.                       (Default: 1)\n\tipver:      Only addresses of family IPv4 or IPv6 will be used if defined  (Default: 0)\n\tstrict:     Require the DNS resolution to succeed and return addresses,\n\t            otherwise marks the underlying server and peers as down and\n\t            forces use of other servers in the upstream block if there\n\t            are any present. A failed resolution can be a timeout, DNS\n\t            server failure, connection refusals, response with no\n\t            addresses, etc.\n```\n\nSee https://www.nginx.com/resources/wiki/modules/domain_resolve/ for details.\n\n## Development\n\n### Prerequisites\n\nTo facilitate local development and enable you to build and test the module,\nyou'll need some tools.\n\n- **[Docker](https://docs.docker.com/get-docker/)**: to provide an environment\n\tto easily reproduce ideal conditions for building and testing.\n- **[act](https://github.com/nektos/act#installation)**: to simulate executing\n\tgithub actions workflows locally to save you from pushing commits just to\n\twatch the CI fail.\n- **[rust](https://www.rust-lang.org/tools/install)**: dependency of\n\t`cargo-make`.\n- **[cargo-make](https://sagiegurari.github.io/cargo-make/#installation)**: to\n\trun common development tasks such as building, testing, and formatting code.\n\n### Task Runner\n\n`cargo-make` is an advanced task runner that will enabled you to easily perform\ncommon development operations like formatting the code, building the module,\nrunning the test suite, and running code analysis. You can see the task\ndefinitions in the file `Makefile.toml`. Installing `cargo-make` will result in\na standalone executable called `makers` as well as a `cargo` extension which\ncan be executed via `cargo make`. As this project is not a `rust` crate, it is\nrecommended to simply use `makers`.\n\nAlso note that for simplicity's sake, the task runner uses docker to run all\ntasks. This means the build binary is not targetting your host platform.\n\n#### Default Task\n\nTo add value, the default task (ie. simply running `makers` alone) will begin\nan interactive bash session inside the docker container used for this project.\n\nThis should help with debugging and general workflow.\n\n#### Formatting\n\nIncorrectly formatted code will cause the github actions linting job to fail.\nTo avoid this, you can run the format task before pushing new changes, like so:\n\n```bash\nmakers format\n```\n\nThis formatting is performed by a tool called `clang-format`. You can find the\nconfig options for this defined in the file `./.clang-format`.\n\n#### Building\n\nYou can build nginx with the module by running the build task, like so:\n\n```bash\nmakers build\n```\n\nThis will output a `./bin/` directory, which will contain the nginx source for\nthe version of nginx defined in the file `./.env` as well as an nginx binary at\n`./bin/sbin/nginx`. You add the directories in `./bin/workdir/src/` to your\neditor's includes path so facilitate local development.\n\n#### Static Code Analysis\n\nYou can run a static analysis on the code via the analyse task:\n\n```bash\nmakers analyse\n```\n\nThis analysis is performed by a tool called `clang-tidy`. You can find the\nconfig options for this defined in the file `./.clang-tidy`.\n\n#### Testing\n\nYou can run the test suite using the test task, like so:\n\n```bash\nmakers test\n```\n\n### Debugging\n\nWe can use `valgrind` and `gdb` on nginx from inside the container.\n\nFirst open an interactive shell in the container with:\n\n```bash\n$ makers\n```\n\nWe'll use that session to run `valgrind`:\n\n```bash\n$ valgrind --vgdb=full --vgdb-error=0 /github/workspace/bin/static/nginx -p/github/workspace/t/servroot -cconf/nginx.conf\n==15== Memcheck, a memory error detector\n==15== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.\n==15== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info\n==15== Command: /github/workspace/bin/static/nginx -p/github/workspace/t/servroot -cconf/nginx.conf\n==15==\n==15== (action at startup) vgdb me ...\n==15==\n==15== TO DEBUG THIS PROCESS USING GDB: start GDB like this\n==15==   /path/to/gdb /github/workspace/bin/static/nginx\n==15== and then give GDB the following command\n==15==   target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=15\n==15== --pid is optional if only one valgrind process is running\n==15==\n```\n\nNext, find the container identifier so we can open another session inside it:\n\n```bash\n$ docker ps\nCONTAINER ID        IMAGE                                     COMMAND             CREATED             STATUS              PORTS                    NAMES\n55fab1e069ba        act-github-actions-nginx-module-toolbox   \"bash\"              4 seconds ago       Up 3 seconds        0.0.0.0:1984-\u003e1984/tcp   serene_newton\n```\n\nUse either the name or ID to execute a bash session inside the container:\n\n```bash\n$ docker exec -it serene_newton bash\n```\n\nWe'll use this session to start `gdb` and target the valgrind gdb server we started in the other session:\n\n```bash\n$ gdb /github/workspace/bin/static/nginx\nGNU gdb (GDB) Red Hat Enterprise Linux 8.0.1-30.amzn2.0.3\nCopyright (C) 2017 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later \u003chttp://gnu.org/licenses/gpl.html\u003e\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"x86_64-redhat-linux-gnu\".\nType \"show configuration\" for configuration details.\nFor bug reporting instructions, please see:\n\u003chttp://www.gnu.org/software/gdb/bugs/\u003e.\nFind the GDB manual and other documentation resources online at:\n\u003chttp://www.gnu.org/software/gdb/documentation/\u003e.\nFor help, type \"help\".\nType \"apropos word\" to search for commands related to \"word\"...\nReading symbols from /github/workspace/bin/static/nginx...done.\n(gdb)\n```\n\nFrom the gdb prompt, target the valgrind process and begin debugging:\n\n```bash\n(gdb) target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=15\nRemote debugging using | /usr/lib64/valgrind/../../bin/vgdb --pid=15\nrelaying data between gdb and process 15\nwarning: remote target does not support file transfer, attempting to access files from local filesystem.\nReading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.\n0x0000000004000ef0 in _start () from /lib64/ld-linux-x86-64.so.2\nMissing separate debuginfos, use: debuginfo-install glibc-2.26-35.amzn2.x86_64\n(gdb)\n```\n\n### Running GitHub Actions\n\nWith `act`, you can simulate the workflow that will run on GitHub servers once\nyou push changes.\n\nThere is more than one job in the main workflow, so you need to specify the\ntest job when you run `act`. For example, you can use this command to run the\ncode format validation:\n\n```shell\nact -vj lint\n```\n\nNote that the `lint` job does not format your code, it only checks that the\nformatting is as expected.\n\nAlso note that `-v` is used to enable verbose mode to give more visibility on\neverything `act` is doing.\n\nThe jobs you can (and should) run locally are `lint`, `build`, `analyse`, and\n`test`. The `test` job depends on the output from the `build` job. To keep the\noutput from the build job, you can add the `-b` flag to `act`, or you may\nsimply use the task runner to build.\n\n### Known Issues\n\nAt the moment? None! 🎉\n\nIf you discover a bug or have a question to raise, please\n[open an issue](https://github.com/nicholaschiasson/ngx_upstream_jdomain/issues/new/choose).\n\n## Original Author\n\nwdaike \u003cwdaike@163.com\u003e (https://github.com/wdaike), Baidu Inc.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicholaschiasson%2Fngx_upstream_jdomain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnicholaschiasson%2Fngx_upstream_jdomain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicholaschiasson%2Fngx_upstream_jdomain/lists"}