Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: gorilla/mux
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.8.0
Choose a base ref
...
head repository: gorilla/mux
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.8.1
Choose a head ref

Commits on Sep 12, 2020

  1. build: CircleCI 2.1 + build matrix (#595)

    * build: CircleCI 2.1 + build matrix
    
    * build: drop Go 1.9 & Go 1.10
    
    * build: remove erroneous version
    elithrar authored Sep 12, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d07530f View commit details

Commits on Sep 14, 2021

  1. Copy the full SHA
    3cf0d01 View commit details

Commits on Dec 12, 2021

  1. docs: update README w.r.t new maintainer ask (#660)

    * Update README.md
    
    * build: gofmt on latest
    elithrar authored Dec 12, 2021
    Copy the full SHA
    91708ff View commit details

Commits on Jun 26, 2022

  1. regexp: use iota instead of hardcoded values for regexType* (#679)

    * regexp: use iota instead of hardcoded values
    mikayelgr authored Jun 26, 2022
    Copy the full SHA
    c889844 View commit details

Commits on Aug 17, 2022

  1. [docs] authenticationMiddleware initialization in the README.md f…

    …ile (#693)
    
    * initial commit
    
    * fix `README.md` - authenticationMiddleware initialization
    amustaque97 authored Aug 17, 2022
    Copy the full SHA
    07eedff View commit details

Commits on Dec 9, 2022

  1. archive mode

    elithrar authored Dec 9, 2022
    Copy the full SHA
    5e1e8c8 View commit details
  2. archive mode

    elithrar authored Dec 9, 2022
    Copy the full SHA
    eb99d7a View commit details

Commits on Jul 15, 2023

  1. Update README.md

    Signed-off-by: Corey Daley <cdaley@redhat.com>
    coreydaley authored Jul 15, 2023
    Copy the full SHA
    7456b4e View commit details
  2. Merge pull request #713 from gorilla/coreydaley-patch-1

    Update README.md
    coreydaley authored Jul 15, 2023
    Copy the full SHA
    abccd7e View commit details

Commits on Jul 23, 2023

  1. [GPT-95] Update go version, add tools for verification and testing (#718

    )
    
    Fixes # https://gorilla-web-toolkit.atlassian.net/browse/GPT-95
    
    **Summary of Changes**
    Added `.github/workflows/test.yml` that runs golangci-lint & go tests on
    any PR created or each push to main branch.
    
    ---------
    
    Signed-off-by: Corey Daley <cdaley@redhat.com>
    Signed-off-by: Apoorva Jagtap <35304110+apoorvajagtap@users.noreply.github.com>
    Co-authored-by: Corey Daley <cdaley@redhat.com>
    apoorvajagtap and coreydaley authored Jul 23, 2023
    Copy the full SHA
    1fa2ee8 View commit details
  2. Delete release-drafter.yml (#719)

    <!--
    For Work In Progress Pull Requests, please use the Draft PR feature,
    see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
    further details.
    
         For a timely review/response, please avoid force-pushing additional
         commits if your PR already received reviews or comments.
    
         Before submitting a Pull Request, please ensure that you have:
    - 📖 Read the Contributing guide:
    https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
    - 📖 Read the Code of Conduct:
    https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
    
         - Provide tests for your changes.
         - Use descriptive commit messages.
    	 - Comment your code where appropriate.
    	 - Squash your commits
         - Update any related documentation.
    
         - Add gorilla/pull-request-reviewers as a Reviewer
    -->
    
    ## What type of PR is this? (check all applicable)
    
    - [ ] Refactor
    - [ ] Feature
    - [ ] Bug Fix
    - [ ] Optimization
    - [ ] Documentation Update
    
    ## Description
    
    ## Related Tickets & Documents
    
    <!--
    For pull requests that relate or close an issue, please include them
    below. We like to follow [Github's guidance on linking issues to pull
    requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
    
    For example having the text: "closes #1234" would connect the current
    pull
    request to issue 1234.  And when we merge the pull request, Github will
    automatically close the issue.
    -->
    
    - Related Issue #
    - Closes #
    
    ## Added/updated tests?
    
    - [ ] Yes
    - [ ] No, and this is why: _please replace this line with details on why
    tests
          have not been included_
    - [ ] I need help with writing tests
    
    ## Run verifications and test
    
    - [ ] `make verify` is passing
    - [ ] `make test` is passing
    
    Signed-off-by: Corey Daley <cdaley@redhat.com>
    coreydaley authored Jul 23, 2023
    Copy the full SHA
    96847b8 View commit details
  3. Delete stale.yml (#720)

    <!--
    For Work In Progress Pull Requests, please use the Draft PR feature,
    see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
    further details.
    
         For a timely review/response, please avoid force-pushing additional
         commits if your PR already received reviews or comments.
    
         Before submitting a Pull Request, please ensure that you have:
    - 📖 Read the Contributing guide:
    https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
    - 📖 Read the Code of Conduct:
    https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
    
         - Provide tests for your changes.
         - Use descriptive commit messages.
    	 - Comment your code where appropriate.
    	 - Squash your commits
         - Update any related documentation.
    
         - Add gorilla/pull-request-reviewers as a Reviewer
    -->
    
    ## What type of PR is this? (check all applicable)
    
    - [ ] Refactor
    - [ ] Feature
    - [ ] Bug Fix
    - [ ] Optimization
    - [ ] Documentation Update
    
    ## Description
    
    ## Related Tickets & Documents
    
    <!--
    For pull requests that relate or close an issue, please include them
    below. We like to follow [Github's guidance on linking issues to pull
    requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
    
    For example having the text: "closes #1234" would connect the current
    pull
    request to issue 1234.  And when we merge the pull request, Github will
    automatically close the issue.
    -->
    
    - Related Issue #
    - Closes #
    
    ## Added/updated tests?
    
    - [ ] Yes
    - [ ] No, and this is why: _please replace this line with details on why
    tests
          have not been included_
    - [ ] I need help with writing tests
    
    ## Run verifications and test
    
    - [ ] `make verify` is passing
    - [ ] `make test` is passing
    
    Signed-off-by: Corey Daley <cdaley@redhat.com>
    coreydaley authored Jul 23, 2023
    Copy the full SHA
    81b48a3 View commit details
  4. Delete AUTHORS (#721)

    <!--
    For Work In Progress Pull Requests, please use the Draft PR feature,
    see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
    further details.
    
         For a timely review/response, please avoid force-pushing additional
         commits if your PR already received reviews or comments.
    
         Before submitting a Pull Request, please ensure that you have:
    - 📖 Read the Contributing guide:
    https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
    - 📖 Read the Code of Conduct:
    https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
    
         - Provide tests for your changes.
         - Use descriptive commit messages.
    	 - Comment your code where appropriate.
    	 - Squash your commits
         - Update any related documentation.
    
         - Add gorilla/pull-request-reviewers as a Reviewer
    -->
    
    ## What type of PR is this? (check all applicable)
    
    - [ ] Refactor
    - [ ] Feature
    - [ ] Bug Fix
    - [ ] Optimization
    - [ ] Documentation Update
    
    ## Description
    
    ## Related Tickets & Documents
    
    <!--
    For pull requests that relate or close an issue, please include them
    below. We like to follow [Github's guidance on linking issues to pull
    requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
    
    For example having the text: "closes #1234" would connect the current
    pull
    request to issue 1234.  And when we merge the pull request, Github will
    automatically close the issue.
    -->
    
    - Related Issue #
    - Closes #
    
    ## Added/updated tests?
    
    - [ ] Yes
    - [ ] No, and this is why: _please replace this line with details on why
    tests
          have not been included_
    - [ ] I need help with writing tests
    
    ## Run verifications and test
    
    - [ ] `make verify` is passing
    - [ ] `make test` is passing
    
    Signed-off-by: Corey Daley <cdaley@redhat.com>
    coreydaley authored Jul 23, 2023
    Copy the full SHA
    2392d7d View commit details
  5. Update LICENSE (#722)

    <!--
    For Work In Progress Pull Requests, please use the Draft PR feature,
    see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
    further details.
    
         For a timely review/response, please avoid force-pushing additional
         commits if your PR already received reviews or comments.
    
         Before submitting a Pull Request, please ensure that you have:
    - 📖 Read the Contributing guide:
    https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
    - 📖 Read the Code of Conduct:
    https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
    
         - Provide tests for your changes.
         - Use descriptive commit messages.
    	 - Comment your code where appropriate.
    	 - Squash your commits
         - Update any related documentation.
    
         - Add gorilla/pull-request-reviewers as a Reviewer
    -->
    
    ## What type of PR is this? (check all applicable)
    
    - [ ] Refactor
    - [ ] Feature
    - [ ] Bug Fix
    - [ ] Optimization
    - [ ] Documentation Update
    
    ## Description
    
    ## Related Tickets & Documents
    
    <!--
    For pull requests that relate or close an issue, please include them
    below. We like to follow [Github's guidance on linking issues to pull
    requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
    
    For example having the text: "closes #1234" would connect the current
    pull
    request to issue 1234.  And when we merge the pull request, Github will
    automatically close the issue.
    -->
    
    - Related Issue #
    - Closes #
    
    ## Added/updated tests?
    
    - [ ] Yes
    - [ ] No, and this is why: _please replace this line with details on why
    tests
          have not been included_
    - [ ] I need help with writing tests
    
    ## Run verifications and test
    
    - [ ] `make verify` is passing
    - [ ] `make test` is passing
    
    Signed-off-by: Corey Daley <cdaley@redhat.com>
    coreydaley authored Jul 23, 2023
    Copy the full SHA
    ff63d0e View commit details

Commits on Jul 25, 2023

  1. Updated the logo in README.md (#724)

    <!--
    For Work In Progress Pull Requests, please use the Draft PR feature,
    see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
    further details.
    
         For a timely review/response, please avoid force-pushing additional
         commits if your PR already received reviews or comments.
    
         Before submitting a Pull Request, please ensure that you have:
    - 📖 Read the Contributing guide:
    https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
    - 📖 Read the Code of Conduct:
    https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
    
         - Provide tests for your changes.
         - Use descriptive commit messages.
    	 - Comment your code where appropriate.
    	 - Squash your commits
         - Update any related documentation.
    
         - Add gorilla/pull-request-reviewers as a Reviewer
    -->
    
    ## What type of PR is this? (check all applicable)
    
    - [ ] Refactor
    - [ ] Feature
    - [ ] Bug Fix
    - [ ] Optimization
    - [x] Documentation Update
    
    ## Description
    
    ## Related Tickets & Documents
    
    <!--
    For pull requests that relate or close an issue, please include them
    below. We like to follow [Github's guidance on linking issues to pull
    requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
    
    For example having the text: "closes #1234" would connect the current
    pull
    request to issue 1234.  And when we merge the pull request, Github will
    automatically close the issue.
    -->
    
    - Related Issue #710
    - Closes #710
    
    ## Added/updated tests?
    
    - [ ] Yes
    - [ ] No, and this is why: _please replace this line with details on why
    tests
          have not been included_
    - [ ] I need help with writing tests
    
    ## Run verifications and test
    
    - [ ] `make verify` is passing
    - [ ] `make test` is passing
    
    Signed-off-by: Sham Karthik S <53367916+shamkarthik@users.noreply.github.com>
    shamkarthik authored Jul 25, 2023
    Copy the full SHA
    753457f View commit details
  2. Update LICENSE (#723)

    <!--
    For Work In Progress Pull Requests, please use the Draft PR feature,
    see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
    further details.
    
         For a timely review/response, please avoid force-pushing additional
         commits if your PR already received reviews or comments.
    
         Before submitting a Pull Request, please ensure that you have:
    - 📖 Read the Contributing guide:
    https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
    - 📖 Read the Code of Conduct:
    https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
    
         - Provide tests for your changes.
         - Use descriptive commit messages.
    	 - Comment your code where appropriate.
    	 - Squash your commits
         - Update any related documentation.
    
         - Add gorilla/pull-request-reviewers as a Reviewer
    -->
    
    ## What type of PR is this? (check all applicable)
    
    - [ ] Refactor
    - [ ] Feature
    - [ ] Bug Fix
    - [ ] Optimization
    - [ ] Documentation Update
    
    ## Description
    
    ## Related Tickets & Documents
    
    <!--
    For pull requests that relate or close an issue, please include them
    below. We like to follow [Github's guidance on linking issues to pull
    requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
    
    For example having the text: "closes #1234" would connect the current
    pull
    request to issue 1234.  And when we merge the pull request, Github will
    automatically close the issue.
    -->
    
    - Related Issue #
    - Closes #
    
    ## Added/updated tests?
    
    - [ ] Yes
    - [ ] No, and this is why: _please replace this line with details on why
    tests
          have not been included_
    - [ ] I need help with writing tests
    
    ## Run verifications and test
    
    - [ ] `make verify` is passing
    - [ ] `make test` is passing
    
    Signed-off-by: Corey Daley <cdaley@redhat.com>
    coreydaley authored Jul 25, 2023
    1
    Copy the full SHA
    809d128 View commit details

Commits on Jul 30, 2023

  1. Update issues.yml (#726)

    <!--
    For Work In Progress Pull Requests, please use the Draft PR feature,
    see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
    further details.
    
         For a timely review/response, please avoid force-pushing additional
         commits if your PR already received reviews or comments.
    
         Before submitting a Pull Request, please ensure that you have:
    - 📖 Read the Contributing guide:
    https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
    - 📖 Read the Code of Conduct:
    https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
    
         - Provide tests for your changes.
         - Use descriptive commit messages.
    	 - Comment your code where appropriate.
    	 - Squash your commits
         - Update any related documentation.
    
         - Add gorilla/pull-request-reviewers as a Reviewer
    -->
    
    ## What type of PR is this? (check all applicable)
    
    - [ ] Refactor
    - [ ] Feature
    - [ ] Bug Fix
    - [ ] Optimization
    - [ ] Documentation Update
    
    ## Description
    
    ## Related Tickets & Documents
    
    <!--
    For pull requests that relate or close an issue, please include them
    below. We like to follow [Github's guidance on linking issues to pull
    requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
    
    For example having the text: "closes #1234" would connect the current
    pull
    request to issue 1234.  And when we merge the pull request, Github will
    automatically close the issue.
    -->
    
    - Related Issue #
    - Closes #
    
    ## Added/updated tests?
    
    - [ ] Yes
    - [ ] No, and this is why: _please replace this line with details on why
    tests
          have not been included_
    - [ ] I need help with writing tests
    
    ## Run verifications and test
    
    - [ ] `make verify` is passing
    - [ ] `make test` is passing
    
    Signed-off-by: Corey Daley <cdaley@redhat.com>
    coreydaley authored Jul 30, 2023
    Copy the full SHA
    cfc696d View commit details
  2. Update issues.yml (#727)

    <!--
    For Work In Progress Pull Requests, please use the Draft PR feature,
    see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
    further details.
    
         For a timely review/response, please avoid force-pushing additional
         commits if your PR already received reviews or comments.
    
         Before submitting a Pull Request, please ensure that you have:
    - 📖 Read the Contributing guide:
    https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
    - 📖 Read the Code of Conduct:
    https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
    
         - Provide tests for your changes.
         - Use descriptive commit messages.
    	 - Comment your code where appropriate.
    	 - Squash your commits
         - Update any related documentation.
    
         - Add gorilla/pull-request-reviewers as a Reviewer
    -->
    
    ## What type of PR is this? (check all applicable)
    
    - [ ] Refactor
    - [ ] Feature
    - [ ] Bug Fix
    - [ ] Optimization
    - [ ] Documentation Update
    
    ## Description
    
    ## Related Tickets & Documents
    
    <!--
    For pull requests that relate or close an issue, please include them
    below. We like to follow [Github's guidance on linking issues to pull
    requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
    
    For example having the text: "closes #1234" would connect the current
    pull
    request to issue 1234.  And when we merge the pull request, Github will
    automatically close the issue.
    -->
    
    - Related Issue #
    - Closes #
    
    ## Added/updated tests?
    
    - [ ] Yes
    - [ ] No, and this is why: _please replace this line with details on why
    tests
          have not been included_
    - [ ] I need help with writing tests
    
    ## Run verifications and test
    
    - [ ] `make verify` is passing
    - [ ] `make test` is passing
    
    Signed-off-by: Corey Daley <cdaley@redhat.com>
    coreydaley authored Jul 30, 2023
    Copy the full SHA
    651928c View commit details

Commits on Jul 31, 2023

  1. run go fmt with Go 1.20 (#725)

    <!--
    For Work In Progress Pull Requests, please use the Draft PR feature,
    see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
    further details.
    
         For a timely review/response, please avoid force-pushing additional
         commits if your PR already received reviews or comments.
    
         Before submitting a Pull Request, please ensure that you have:
    - 📖 Read the Contributing guide:
    https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
    - 📖 Read the Code of Conduct:
    https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
    
         - Provide tests for your changes.
         - Use descriptive commit messages.
    	 - Comment your code where appropriate.
    	 - Squash your commits
         - Update any related documentation.
    
         - Add gorilla/pull-request-reviewers as a Reviewer
    -->
    
    ## What type of PR is this? (check all applicable)
    
    - [ ] Refactor
    - [ ] Feature
    - [ ] Bug Fix
    - [ ] Optimization
    - [x] Documentation Update
    
    ## Description
    
    `go fmt` now formats godoc comments. I apply it.
    
    ## Related Tickets & Documents
    
    <!--
    For pull requests that relate or close an issue, please include them
    below. We like to follow [Github's guidance on linking issues to pull
    requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
    
    For example having the text: "closes #1234" would connect the current
    pull
    request to issue 1234.  And when we merge the pull request, Github will
    automatically close the issue.
    -->
    
    - Related Issue #
    - Closes #
    
    ## Added/updated tests?
    
    - [ ] Yes
    - [x] No, and this is why: this pull request updates only comments
    - [ ] I need help with writing tests
    
    ## Run verifications and test
    
    - [x] `make verify` is passing
    - [x] `make test` is passing
    
    Co-authored-by: Corey Daley <cdaley@redhat.com>
    shogo82148 and coreydaley authored Jul 31, 2023
    Copy the full SHA
    546dd0c View commit details

Commits on Aug 16, 2023

  1. Fix Single Page Application example in README.md file (#678)

    Fixes #588
    
    **Summary of Changes**
    
    1. Add test case to validate proposed fix (both negative and positive
    test case).
    2. Update `README.md` file.
    
    PS: If you want to verify how I'm able to reproduce the issue and tried
    my fix. Here is a link of my local PR where I have configured `Github
    Action` to execute same test cases on all the platforms i.e. `ubuntu`,
    `macos` and `windows`.
    
    PR link: amustaque97#1
    
    > PS: Make sure your PR includes/updates tests! If you need help with
    this part, just ask!
    
    ---------
    
    Co-authored-by: Corey Daley <cdaley@redhat.com>
    amustaque97 and coreydaley authored Aug 16, 2023
    Copy the full SHA
    24c3e7f View commit details

Commits on Aug 17, 2023

  1. [BUG] Inconsistent HTTP status code on query mismatch (#712)

    The logical behavior of a router should return an HTTP status code of
    404 when a request fails to satisfy route validation logic. Previously,
    MUX was returning a 405 HTTP status code in some rare scenarios, which
    was not valid in its case.
    
    For more info, See: #704
    
    Fixes #704 
    
    **Summary of Changes**
    
    1. Clear the mismatch error of the previous validations on method match.
    2. Added related tests
    
    > PS: Make sure your PR includes/updates tests! If you need help with
    this part, just ask!
    
    Co-authored-by: Corey Daley <cdaley@redhat.com>
    soheilrt and coreydaley authored Aug 17, 2023
    Copy the full SHA
    395ad81 View commit details
  2. Clarify documentation examples of Route methods (#672)

    Fixes #666 
    
    **Summary of Changes**
    
    1. Update `Route` method documentation comments where the example in the
    comments showed a `Router` before. Updated method names include:
        * `Headers`
        * `HeadersRegexp`
        * `Host`
        * `Path`
        * `Queries`
        * `Subrouter`
        * `URL`
    
    Notes:
    * This includes what PR #667 did plus some changes requested by a
    maintainer in the comments
    * I was a little torn about changing the example in `Subrouter` since
    `(*Router).Host()` (like several `(*Router)` methods) just calls
    `(*Router).NewRoute().Host()` so I understand if maintainers are
    ambivalent about that example or want it to remain the same.
    
    Signed-off-by: Corey Daley <cdaley@redhat.com>
    Co-authored-by: Andrew Brown <andrew.brown@logicmonitor.com>
    Co-authored-by: Corey Daley <cdaley@redhat.com>
    3 people authored Aug 17, 2023
    Copy the full SHA
    79f2f45 View commit details
  3. changed the routeVariables text content. (#708)

    Before changing the context there is a blind spot, and for this reason,
    decided to add a line break.
    
    Co-authored-by: Corey Daley <cdaley@redhat.com>
    sumanpaikdev and coreydaley authored Aug 17, 2023
    Copy the full SHA
    85123bf View commit details

Commits on Aug 24, 2023

  1. Add GetVarNames() (#676)

    **Summary of Changes**
    
    1. Added `r.GetVarNames()` function to list all vars a route might need
    in order to call `r.URL()`
    
    ---------
    
    Co-authored-by: Anonymous <anonymous@github.com>
    Co-authored-by: Corey Daley <cdaley@redhat.com>
    3 people authored Aug 24, 2023
    Copy the full SHA
    4a671cb View commit details

Commits on Sep 21, 2023

  1. fix SPA handler in README.md (#733)

    <!--
    For Work In Progress Pull Requests, please use the Draft PR feature,
    see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
    further details.
    
         For a timely review/response, please avoid force-pushing additional
         commits if your PR already received reviews or comments.
    
         Before submitting a Pull Request, please ensure that you have:
    - 📖 Read the Contributing guide:
    https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
    - 📖 Read the Code of Conduct:
    https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
    
         - Provide tests for your changes.
         - Use descriptive commit messages.
    	 - Comment your code where appropriate.
    	 - Squash your commits
         - Update any related documentation.
    
         - Add gorilla/pull-request-reviewers as a Reviewer
    -->
    
    ## What type of PR is this? (check all applicable)
    
    - [ ] Refactor
    - [ ] Feature
    - [ ] Bug Fix
    - [ ] Optimization
    - [X] Documentation Update
    - [ ] Go Version Update
    - [ ] Dependency Update
    
    ## Description
    
    Changed the SPA handler example in README.md in two areas. First, made
    sure to actually include the requested path in the call to
    `filepath.Join`. Secondly, if the requested path hits a directory, I
    think it would be beneficial to also serve the `indexPath` file, and not
    list the directory contents. I also edited the comments in the
    `README.md` file accordingly.
    
    ## Related Tickets & Documents
    
    <!--
    For pull requests that relate or close an issue, please include them
    below. We like to follow [Github's guidance on linking issues to pull
    requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
    
    For example having the text: "closes #1234" would connect the current
    pull
    request to issue 1234.  And when we merge the pull request, Github will
    automatically close the issue.
    -->
    
    - Related Issue #
    - Closes #
    
    ## Added/updated tests?
    
    - [ ] Yes
    - [X] No, and this is why: I only changed the `README.md`, if any tests
    are necessary please let me know
    - [ ] I need help with writing tests
    
    ## Run verifications and test
    
    - [ ] `make verify` is passing
    - [ ] `make test` is passing
    sy9 authored Sep 21, 2023
    Copy the full SHA
    3401478 View commit details

Commits on Oct 18, 2023

  1. update GitHub workflows (#734)

    <!--
    For Work In Progress Pull Requests, please use the Draft PR feature,
    see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
    further details.
    
         For a timely review/response, please avoid force-pushing additional
         commits if your PR already received reviews or comments.
    
         Before submitting a Pull Request, please ensure that you have:
    - 📖 Read the Contributing guide:
    https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
    - 📖 Read the Code of Conduct:
    https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
    
         - Provide tests for your changes.
         - Use descriptive commit messages.
    	 - Comment your code where appropriate.
    	 - Squash your commits
         - Update any related documentation.
    
         - Add gorilla/pull-request-reviewers as a Reviewer
    -->
    
    ## What type of PR is this? (check all applicable)
    
    - [x] Refactor
    - [ ] Feature
    - [ ] Bug Fix
    - [ ] Optimization
    - [ ] Documentation Update
    - [ ] Go Version Update
    - [ ] Dependency Update
    
    ## Description
    
    ## Related Tickets & Documents
    
    <!--
    For pull requests that relate or close an issue, please include them
    below. We like to follow [Github's guidance on linking issues to pull
    requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
    
    For example having the text: "closes #1234" would connect the current
    pull
    request to issue 1234.  And when we merge the pull request, Github will
    automatically close the issue.
    -->
    
    - Related Issue #
    - Closes #
    
    ## Added/updated tests?
    
    - [ ] Yes
    - [ ] No, and this is why: _please replace this line with details on why
    tests
          have not been included_
    - [ ] I need help with writing tests
    
    ## Run verifications and test
    
    - [x] `make verify` is passing
    - [x] `make test` is passing
    coreydaley authored Oct 18, 2023
    Copy the full SHA
    b4617d0 View commit details
Showing with 531 additions and 239 deletions.
  1. +0 −87 .circleci/config.yml
  2. +20 −0 .editorconfig
  3. +0 −8 .github/release-drafter.yml
  4. +0 −12 .github/stale.yml
  5. +21 −0 .github/workflows/issues.yml
  6. +37 −0 .github/workflows/security.yml
  7. +35 −0 .github/workflows/test.yml
  8. +32 −0 .github/workflows/verify.yml
  9. +1 −0 .gitignore
  10. +0 −8 AUTHORS
  11. +1 −1 LICENSE
  12. +34 −0 Makefile
  13. +34 −27 README.md
  14. +12 −13 doc.go
  15. +35 −0 example_route_vars_test.go
  16. +1 −1 go.mod
  17. +76 −19 middleware_test.go
  18. +9 −7 mux.go
  19. +11 −4 mux_httpserver_test.go
  20. +96 −5 mux_test.go
  21. +5 −5 regexp.go
  22. +2 −2 regexp_test.go
  23. +69 −40 route.go
87 changes: 0 additions & 87 deletions .circleci/config.yml

This file was deleted.

20 changes: 20 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
; https://editorconfig.org/

root = true

[*]
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
indent_style = space
indent_size = 2

[{Makefile,go.mod,go.sum,*.go,.gitmodules}]
indent_style = tab
indent_size = 4

[*.md]
indent_size = 4
trim_trailing_whitespace = false

eclint_indent_style = unset
8 changes: 0 additions & 8 deletions .github/release-drafter.yml

This file was deleted.

12 changes: 0 additions & 12 deletions .github/stale.yml

This file was deleted.

21 changes: 21 additions & 0 deletions .github/workflows/issues.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add all the issues created to the project.
name: Add issue or pull request to Project

on:
issues:
types:
- opened
pull_request_target:
types:
- opened
- reopened

jobs:
add-to-project:
runs-on: ubuntu-latest
steps:
- name: Add issue to project
uses: actions/add-to-project@v0.5.0
with:
project-url: https://github.com/orgs/gorilla/projects/4
github-token: ${{ secrets.ADD_TO_PROJECT_TOKEN }}
37 changes: 37 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Security
on:
push:
branches:
- main
pull_request:
branches:
- main
permissions:
contents: read
jobs:
scan:
strategy:
matrix:
go: ['1.20','1.21']
fail-fast: true
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Setup Go ${{ matrix.go }}
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go }}
cache: false

- name: Run GoSec
uses: securego/gosec@master
with:
args: -exclude-dir examples ./...

- name: Run GoVulnCheck
uses: golang/govulncheck-action@v1
with:
go-version-input: ${{ matrix.go }}
go-package: ./...
35 changes: 35 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Test
on:
push:
branches:
- main
pull_request:
branches:
- main
permissions:
contents: read
jobs:
unit:
strategy:
matrix:
go: ['1.20','1.21']
os: [ubuntu-latest, macos-latest, windows-latest]
fail-fast: true
runs-on: ${{ matrix.os }}
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Setup Go ${{ matrix.go }}
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go }}
cache: false

- name: Run Tests
run: go test -race -cover -coverprofile=coverage -covermode=atomic -v ./...

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: ./coverage
32 changes: 32 additions & 0 deletions .github/workflows/verify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Verify
on:
push:
branches:
- main
pull_request:
branches:
- main
permissions:
contents: read
jobs:
lint:
strategy:
matrix:
go: ['1.20','1.21']
fail-fast: true
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Setup Go ${{ matrix.go }}
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go }}
cache: false

- name: Run GolangCI-Lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.53
args: --timeout=5m
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
coverage.coverprofile
8 changes: 0 additions & 8 deletions AUTHORS

This file was deleted.

2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved.
Copyright (c) 2023 The Gorilla Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
34 changes: 34 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
GO_LINT=$(shell which golangci-lint 2> /dev/null || echo '')
GO_LINT_URI=github.com/golangci/golangci-lint/cmd/golangci-lint@latest

GO_SEC=$(shell which gosec 2> /dev/null || echo '')
GO_SEC_URI=github.com/securego/gosec/v2/cmd/gosec@latest

GO_VULNCHECK=$(shell which govulncheck 2> /dev/null || echo '')
GO_VULNCHECK_URI=golang.org/x/vuln/cmd/govulncheck@latest

.PHONY: golangci-lint
golangci-lint:
$(if $(GO_LINT), ,go install $(GO_LINT_URI))
@echo "##### Running golangci-lint"
golangci-lint run -v

.PHONY: gosec
gosec:
$(if $(GO_SEC), ,go install $(GO_SEC_URI))
@echo "##### Running gosec"
gosec ./...

.PHONY: govulncheck
govulncheck:
$(if $(GO_VULNCHECK), ,go install $(GO_VULNCHECK_URI))
@echo "##### Running govulncheck"
govulncheck ./...

.PHONY: verify
verify: golangci-lint gosec govulncheck

.PHONY: test
test:
@echo "##### Running tests"
go test -race -cover -coverprofile=coverage.coverprofile -covermode=atomic -v ./...
61 changes: 34 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# gorilla/mux

[![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux)
[![CircleCI](https://circleci.com/gh/gorilla/mux.svg?style=svg)](https://circleci.com/gh/gorilla/mux)
[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge)
![testing](https://github.com/gorilla/mux/actions/workflows/test.yml/badge.svg)
[![codecov](https://codecov.io/github/gorilla/mux/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/mux)
[![godoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux)
[![sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge)

![Gorilla Logo](https://cloud-cdn.questionable.services/gorilla-icon-64.png)

https://www.gorillatoolkit.org/pkg/mux
![Gorilla Logo](https://github.com/gorilla/.github/assets/53367916/d92caabf-98e0-473e-bfbf-ab554ba435e5)

Package `gorilla/mux` implements a request router and dispatcher for matching incoming requests to
their respective handler.
@@ -247,32 +247,25 @@ type spaHandler struct {
// file located at the index path on the SPA handler will be served. This
// is suitable behavior for serving an SPA (single page application).
func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// get the absolute path to prevent directory traversal
path, err := filepath.Abs(r.URL.Path)
if err != nil {
// if we failed to get the absolute path respond with a 400 bad request
// and stop
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

// prepend the path with the path to the static directory
path = filepath.Join(h.staticPath, path)
// Join internally call path.Clean to prevent directory traversal
path := filepath.Join(h.staticPath, r.URL.Path)

// check whether a file exists at the given path
_, err = os.Stat(path)
if os.IsNotExist(err) {
// file does not exist, serve index.html
// check whether a file exists or is a directory at the given path
fi, err := os.Stat(path)
if os.IsNotExist(err) || fi.IsDir() {
// file does not exist or path is a directory, serve index.html
http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath))
return
} else if err != nil {
// if we got an error (that wasn't that the file doesn't exist) stating the
// file, return a 500 internal server error and stop
}

if err != nil {
// if we got an error (that wasn't that the file doesn't exist) stating the
// file, return a 500 internal server error and stop
http.Error(w, err.Error(), http.StatusInternalServerError)
return
return
}

// otherwise, use http.FileServer to serve the static dir
// otherwise, use http.FileServer to serve the static file
http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r)
}

@@ -375,6 +368,19 @@ url, err := r.Get("article").URL("subdomain", "news",
"id", "42")
```

To find all the required variables for a given route when calling `URL()`, the method `GetVarNames()` is available:
```go
r := mux.NewRouter()
r.Host("{domain}").
Path("/{group}/{item_id}").
Queries("some_data1", "{some_data1}").
Queries("some_data2", "{some_data2}").
Name("article")

// Will print [domain group item_id some_data1 some_data2] <nil>
fmt.Println(r.Get("article").GetVarNames())

```
### Walking Routes

The `Walk` function on `mux.Router` can be used to visit all of the routes that are registered on a router. For example,
@@ -572,7 +578,7 @@ func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler
r := mux.NewRouter()
r.HandleFunc("/", handler)

amw := authenticationMiddleware{}
amw := authenticationMiddleware{tokenUsers: make(map[string]string)}
amw.Populate()

r.Use(amw.Middleware)
@@ -758,7 +764,8 @@ func TestMetricsHandler(t *testing.T) {
rr := httptest.NewRecorder()
// Need to create a router that we can pass the request through so that the vars will be added to the context
// To add the vars to the context,
// we need to create a router through which we can pass the request.
router := mux.NewRouter()
router.HandleFunc("/metrics/{type}", MetricsHandler)
router.ServeHTTP(rr, req)
25 changes: 12 additions & 13 deletions doc.go
Original file line number Diff line number Diff line change
@@ -10,18 +10,18 @@ http.ServeMux, mux.Router matches incoming requests against a list of
registered routes and calls a handler for the route that matches the URL
or other conditions. The main features are:
* Requests can be matched based on URL host, path, path prefix, schemes,
header and query values, HTTP methods or using custom matchers.
* URL hosts, paths and query values can have variables with an optional
regular expression.
* Registered URLs can be built, or "reversed", which helps maintaining
references to resources.
* Routes can be used as subrouters: nested routes are only tested if the
parent route matches. This is useful to define groups of routes that
share common conditions like a host, a path prefix or other repeated
attributes. As a bonus, this optimizes request matching.
* It implements the http.Handler interface so it is compatible with the
standard http.ServeMux.
- Requests can be matched based on URL host, path, path prefix, schemes,
header and query values, HTTP methods or using custom matchers.
- URL hosts, paths and query values can have variables with an optional
regular expression.
- Registered URLs can be built, or "reversed", which helps maintaining
references to resources.
- Routes can be used as subrouters: nested routes are only tested if the
parent route matches. This is useful to define groups of routes that
share common conditions like a host, a path prefix or other repeated
attributes. As a bonus, this optimizes request matching.
- It implements the http.Handler interface so it is compatible with the
standard http.ServeMux.
Let's start registering a couple of URL paths and handlers:
@@ -301,6 +301,5 @@ A more complex authentication middleware, which maps session token to users, cou
r.Use(amw.Middleware)
Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to.
*/
package mux
35 changes: 35 additions & 0 deletions example_route_vars_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package mux_test

import (
"fmt"
"github.com/gorilla/mux"
)

// This example demonstrates building a dynamic URL using
// required vars and values retrieve from another source
func ExampleRoute_GetVarNames() {
r := mux.NewRouter()

route := r.Host("{domain}").
Path("/{group}/{item_id}").
Queries("some_data1", "{some_data1}").
Queries("some_data2_and_3", "{some_data2}.{some_data3}")

dataSource := func(key string) string {
return "my_value_for_" + key
}

varNames, _ := route.GetVarNames()

pairs := make([]string, 0, len(varNames)*2)

for _, varName := range varNames {
pairs = append(pairs, varName, dataSource(varName))
}

url, err := route.URL(pairs...)
if err != nil {
panic(err)
}
fmt.Println(url.String())
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/gorilla/mux

go 1.12
go 1.20
95 changes: 76 additions & 19 deletions middleware_test.go
Original file line number Diff line number Diff line change
@@ -158,7 +158,10 @@ func TestMiddlewareExecution(t *testing.T) {

router := NewRouter()
router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
w.Write(handlerStr)
_, err := w.Write(handlerStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
})

t.Run("responds normally without middleware", func(t *testing.T) {
@@ -178,7 +181,10 @@ func TestMiddlewareExecution(t *testing.T) {

router.Use(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write(mwStr)
_, err := w.Write(mwStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
h.ServeHTTP(w, r)
})
})
@@ -196,11 +202,17 @@ func TestMiddlewareNotFound(t *testing.T) {

router := NewRouter()
router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
w.Write(handlerStr)
_, err := w.Write(handlerStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
})
router.Use(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write(mwStr)
_, err := w.Write(mwStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
h.ServeHTTP(w, r)
})
})
@@ -221,7 +233,10 @@ func TestMiddlewareNotFound(t *testing.T) {
req := newRequest("GET", "/notfound")

router.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("Custom 404 handler"))
_, err := rw.Write([]byte("Custom 404 handler"))
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
})
router.ServeHTTP(rw, req)

@@ -237,12 +252,18 @@ func TestMiddlewareMethodMismatch(t *testing.T) {

router := NewRouter()
router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
w.Write(handlerStr)
_, err := w.Write(handlerStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
}).Methods("GET")

router.Use(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write(mwStr)
_, err := w.Write(mwStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
h.ServeHTTP(w, r)
})
})
@@ -262,7 +283,10 @@ func TestMiddlewareMethodMismatch(t *testing.T) {
req := newRequest("POST", "/")

router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("Method not allowed"))
_, err := rw.Write([]byte("Method not allowed"))
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
})
router.ServeHTTP(rw, req)

@@ -278,17 +302,26 @@ func TestMiddlewareNotFoundSubrouter(t *testing.T) {

router := NewRouter()
router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
w.Write(handlerStr)
_, err := w.Write(handlerStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
})

subrouter := router.PathPrefix("/sub/").Subrouter()
subrouter.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
w.Write(handlerStr)
_, err := w.Write(handlerStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
})

router.Use(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write(mwStr)
_, err := w.Write(mwStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
h.ServeHTTP(w, r)
})
})
@@ -308,7 +341,10 @@ func TestMiddlewareNotFoundSubrouter(t *testing.T) {
req := newRequest("GET", "/sub/notfound")

subrouter.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("Custom 404 handler"))
_, err := rw.Write([]byte("Custom 404 handler"))
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
})
router.ServeHTTP(rw, req)

@@ -324,17 +360,26 @@ func TestMiddlewareMethodMismatchSubrouter(t *testing.T) {

router := NewRouter()
router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
w.Write(handlerStr)
_, err := w.Write(handlerStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
})

subrouter := router.PathPrefix("/sub/").Subrouter()
subrouter.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
w.Write(handlerStr)
_, err := w.Write(handlerStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
}).Methods("GET")

router.Use(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write(mwStr)
_, err := w.Write(mwStr)
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
h.ServeHTTP(w, r)
})
})
@@ -354,7 +399,10 @@ func TestMiddlewareMethodMismatchSubrouter(t *testing.T) {
req := newRequest("POST", "/sub/")

router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("Method not allowed"))
_, err := rw.Write([]byte("Method not allowed"))
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
})
router.ServeHTTP(rw, req)

@@ -508,7 +556,10 @@ func TestMiddlewareOnMultiSubrouter(t *testing.T) {
secondSubRouter := router.PathPrefix("/").Subrouter()

router.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte(notFound))
_, err := rw.Write([]byte(notFound))
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
})

firstSubRouter.HandleFunc("/first", func(w http.ResponseWriter, r *http.Request) {
@@ -521,14 +572,20 @@ func TestMiddlewareOnMultiSubrouter(t *testing.T) {

firstSubRouter.Use(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(first))
_, err := w.Write([]byte(first))
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
h.ServeHTTP(w, r)
})
})

secondSubRouter.Use(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(second))
_, err := w.Write([]byte(second))
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
h.ServeHTTP(w, r)
})
})
16 changes: 9 additions & 7 deletions mux.go
Original file line number Diff line number Diff line change
@@ -31,24 +31,26 @@ func NewRouter() *Router {
// It implements the http.Handler interface, so it can be registered to serve
// requests:
//
// var router = mux.NewRouter()
// var router = mux.NewRouter()
//
// func main() {
// http.Handle("/", router)
// }
// func main() {
// http.Handle("/", router)
// }
//
// Or, for Google App Engine, register it in a init() function:
//
// func init() {
// http.Handle("/", router)
// }
// func init() {
// http.Handle("/", router)
// }
//
// This will send all incoming requests to the router.
type Router struct {
// Configurable Handler to be used when no route matches.
// This can be used to render your own 404 Not Found errors.
NotFoundHandler http.Handler

// Configurable Handler to be used when the request method does not match the route.
// This can be used to render your own 405 Method Not Allowed errors.
MethodNotAllowedHandler http.Handler

// Routes to be matched, in order.
15 changes: 11 additions & 4 deletions mux_httpserver_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
//go:build go1.9
// +build go1.9

package mux

import (
"bytes"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"testing"
@@ -13,10 +14,16 @@ import (
func TestSchemeMatchers(t *testing.T) {
router := NewRouter()
router.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("hello http world"))
_, err := rw.Write([]byte("hello http world"))
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
}).Schemes("http")
router.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("hello https world"))
_, err := rw.Write([]byte("hello https world"))
if err != nil {
t.Fatalf("Failed writing HTTP response: %v", err)
}
}).Schemes("https")

assertResponseBody := func(t *testing.T, s *httptest.Server, expectedBody string) {
@@ -27,7 +34,7 @@ func TestSchemeMatchers(t *testing.T) {
if resp.StatusCode != 200 {
t.Fatalf("expected a status code of 200, got %v", resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("unexpected error reading body: %v", err)
}
101 changes: 96 additions & 5 deletions mux_test.go
Original file line number Diff line number Diff line change
@@ -10,7 +10,8 @@ import (
"context"
"errors"
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
"net/http/httptest"
"net/url"
@@ -2068,6 +2069,53 @@ func TestNoMatchMethodErrorHandler(t *testing.T) {
}
}

func TestMultipleDefinitionOfSamePathWithDifferentMethods(t *testing.T) {
emptyHandler := func(w http.ResponseWriter, r *http.Request) {}

r := NewRouter()
r.HandleFunc("/api", emptyHandler).Methods("POST")
r.HandleFunc("/api", emptyHandler).Queries("time", "{time:[0-9]+}").Methods("GET")

t.Run("Post Method should be matched properly", func(t *testing.T) {
req, _ := http.NewRequest("POST", "http://localhost/api", nil)
match := new(RouteMatch)
matched := r.Match(req, match)
if !matched {
t.Error("Should have matched route for methods")
}
if match.MatchErr != nil {
t.Error("Should not have any matching error. Found:", match.MatchErr)
}
})

t.Run("Get Method with invalid query value should not match", func(t *testing.T) {
req, _ := http.NewRequest("GET", "http://localhost/api?time=-4", nil)
match := new(RouteMatch)
matched := r.Match(req, match)
if matched {
t.Error("Should not have matched route for methods")
}
if match.MatchErr != ErrNotFound {
t.Error("Should have ErrNotFound error. Found:", match.MatchErr)
}
})

t.Run("A mismach method of a valid path should return ErrMethodMismatch", func(t *testing.T) {
r := NewRouter()
r.HandleFunc("/api2", emptyHandler).Methods("POST")
req, _ := http.NewRequest("GET", "http://localhost/api2", nil)
match := new(RouteMatch)
matched := r.Match(req, match)
if matched {
t.Error("Should not have matched route for methods")
}
if match.MatchErr != ErrMethodMismatch {
t.Error("Should have ErrMethodMismatch error. Found:", match.MatchErr)
}
})

}

func TestErrMatchNotFound(t *testing.T) {
emptyHandler := func(w http.ResponseWriter, r *http.Request) {}

@@ -2136,7 +2184,10 @@ type methodsSubrouterTest struct {
// methodHandler writes the method string in response.
func methodHandler(method string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(method))
_, err := w.Write([]byte(method))
if err != nil {
log.Printf("Failed writing HTTP response: %v", err)
}
}
}

@@ -2778,7 +2829,7 @@ func TestSubrouterCustomMethodNotAllowed(t *testing.T) {
tt.Errorf("Expected status code 405 (got %d)", w.Code)
}

b, err := ioutil.ReadAll(w.Body)
b, err := io.ReadAll(w.Body)
if err != nil {
tt.Errorf("failed to read body: %v", err)
}
@@ -2828,6 +2879,40 @@ func TestContextMiddleware(t *testing.T) {
r.ServeHTTP(rec, req)
}

func TestGetVarNames(t *testing.T) {
r := NewRouter()

route := r.Host("{domain}").
Path("/{group}/{item_id}").
Queries("some_data1", "{some_data1}").
Queries("some_data2_and_3", "{some_data2}.{some_data3}")

// Order of vars in the slice is not guaranteed, so just check for existence
expected := map[string]bool{
"domain": true,
"group": true,
"item_id": true,
"some_data1": true,
"some_data2": true,
"some_data3": true,
}

varNames, err := route.GetVarNames()
if err != nil {
t.Fatal(err)
}

if len(varNames) != len(expected) {
t.Fatalf("expected %d names, got %d", len(expected), len(varNames))
}

for _, varName := range varNames {
if !expected[varName] {
t.Fatalf("got unexpected %s", varName)
}
}
}

// mapToPairs converts a string map to a slice of string pairs
func mapToPairs(m map[string]string) []string {
var i int
@@ -2859,7 +2944,10 @@ func stringMapEqual(m1, m2 map[string]string) bool {
// http.ResponseWriter.
func stringHandler(s string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(s))
_, err := w.Write([]byte(s))
if err != nil {
log.Printf("Failed writing HTTP response: %v", err)
}
}
}

@@ -2892,7 +2980,10 @@ func newRequest(method, url string) *http.Request {

// Simulate writing to wire
var buff bytes.Buffer
req.Write(&buff)
err = req.Write(&buff)
if err != nil {
log.Printf("Failed writing HTTP request: %v", err)
}
ioreader := bufio.NewReader(&buff)

// Parse request off of 'wire'
10 changes: 5 additions & 5 deletions regexp.go
Original file line number Diff line number Diff line change
@@ -22,10 +22,10 @@ type routeRegexpOptions struct {
type regexpType int

const (
regexpTypePath regexpType = 0
regexpTypeHost regexpType = 1
regexpTypePrefix regexpType = 2
regexpTypeQuery regexpType = 3
regexpTypePath regexpType = iota
regexpTypeHost
regexpTypePrefix
regexpTypeQuery
)

// newRouteRegexp parses a route template and returns a routeRegexp,
@@ -195,7 +195,7 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {

// url builds a URL part using the given values.
func (r *routeRegexp) url(values map[string]string) (string, error) {
urlValues := make([]interface{}, len(r.varsN), len(r.varsN))
urlValues := make([]interface{}, len(r.varsN))
for k, v := range r.varsN {
value, ok := values[v]
if !ok {
4 changes: 2 additions & 2 deletions regexp_test.go
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ func Benchmark_findQueryKey(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
for key, _ := range all {
for key := range all {
_, _ = findFirstQueryKey(query, key)
}
}
@@ -79,7 +79,7 @@ func Benchmark_findQueryKeyGoLib(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
for key, _ := range all {
for key := range all {
v := u.Query()[key]
if len(v) > 0 {
_ = v[0]
109 changes: 69 additions & 40 deletions route.go
Original file line number Diff line number Diff line change
@@ -64,8 +64,18 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
match.MatchErr = nil
}

matchErr = nil
matchErr = nil // nolint:ineffassign
return false
} else {
// Multiple routes may share the same path but use different HTTP methods. For instance:
// Route 1: POST "/users/{id}".
// Route 2: GET "/users/{id}", parameters: "id": "[0-9]+".
//
// The router must handle these cases correctly. For a GET request to "/users/abc" with "id" as "-2",
// The router should return a "Not Found" error as no route fully matches this request.
if match.MatchErr == ErrMethodMismatch {
match.MatchErr = nil
}
}
}

@@ -230,9 +240,9 @@ func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool {
// Headers adds a matcher for request header values.
// It accepts a sequence of key/value pairs to be matched. For example:
//
// r := mux.NewRouter()
// r.Headers("Content-Type", "application/json",
// "X-Requested-With", "XMLHttpRequest")
// r := mux.NewRouter().NewRoute()
// r.Headers("Content-Type", "application/json",
// "X-Requested-With", "XMLHttpRequest")
//
// The above route will only match if both request header values match.
// If the value is an empty string, it will match any value if the key is set.
@@ -255,9 +265,9 @@ func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool {
// HeadersRegexp accepts a sequence of key/value pairs, where the value has regex
// support. For example:
//
// r := mux.NewRouter()
// r.HeadersRegexp("Content-Type", "application/(text|json)",
// "X-Requested-With", "XMLHttpRequest")
// r := mux.NewRouter().NewRoute()
// r.HeadersRegexp("Content-Type", "application/(text|json)",
// "X-Requested-With", "XMLHttpRequest")
//
// The above route will only match if both the request header matches both regular expressions.
// If the value is an empty string, it will match any value if the key is set.
@@ -283,10 +293,10 @@ func (r *Route) HeadersRegexp(pairs ...string) *Route {
//
// For example:
//
// r := mux.NewRouter()
// r.Host("www.example.com")
// r.Host("{subdomain}.domain.com")
// r.Host("{subdomain:[a-z]+}.domain.com")
// r := mux.NewRouter().NewRoute()
// r.Host("www.example.com")
// r.Host("{subdomain}.domain.com")
// r.Host("{subdomain:[a-z]+}.domain.com")
//
// Variable names must be unique in a given route. They can be retrieved
// calling mux.Vars(request).
@@ -342,11 +352,11 @@ func (r *Route) Methods(methods ...string) *Route {
//
// For example:
//
// r := mux.NewRouter()
// r.Path("/products/").Handler(ProductsHandler)
// r.Path("/products/{key}").Handler(ProductsHandler)
// r.Path("/articles/{category}/{id:[0-9]+}").
// Handler(ArticleHandler)
// r := mux.NewRouter().NewRoute()
// r.Path("/products/").Handler(ProductsHandler)
// r.Path("/products/{key}").Handler(ProductsHandler)
// r.Path("/articles/{category}/{id:[0-9]+}").
// Handler(ArticleHandler)
//
// Variable names must be unique in a given route. They can be retrieved
// calling mux.Vars(request).
@@ -377,8 +387,8 @@ func (r *Route) PathPrefix(tpl string) *Route {
// It accepts a sequence of key/value pairs. Values may define variables.
// For example:
//
// r := mux.NewRouter()
// r.Queries("foo", "bar", "id", "{id:[0-9]+}")
// r := mux.NewRouter().NewRoute()
// r.Queries("foo", "bar", "id", "{id:[0-9]+}")
//
// The above route will only match if the URL contains the defined queries
// values, e.g.: ?foo=bar&id=42.
@@ -473,11 +483,11 @@ func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route {
//
// It will test the inner routes only if the parent route matched. For example:
//
// r := mux.NewRouter()
// s := r.Host("www.example.com").Subrouter()
// s.HandleFunc("/products/", ProductsHandler)
// s.HandleFunc("/products/{key}", ProductHandler)
// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler)
// r := mux.NewRouter().NewRoute()
// s := r.Host("www.example.com").Subrouter()
// s.HandleFunc("/products/", ProductsHandler)
// s.HandleFunc("/products/{key}", ProductHandler)
// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler)
//
// Here, the routes registered in the subrouter won't be tested if the host
// doesn't match.
@@ -497,36 +507,36 @@ func (r *Route) Subrouter() *Router {
// It accepts a sequence of key/value pairs for the route variables. For
// example, given this route:
//
// r := mux.NewRouter()
// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
// Name("article")
// r := mux.NewRouter()
// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
// Name("article")
//
// ...a URL for it can be built using:
//
// url, err := r.Get("article").URL("category", "technology", "id", "42")
// url, err := r.Get("article").URL("category", "technology", "id", "42")
//
// ...which will return an url.URL with the following path:
//
// "/articles/technology/42"
// "/articles/technology/42"
//
// This also works for host variables:
//
// r := mux.NewRouter()
// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
// Host("{subdomain}.domain.com").
// Name("article")
// r := mux.NewRouter()
// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
// Host("{subdomain}.domain.com").
// Name("article")
//
// // url.String() will be "http://news.domain.com/articles/technology/42"
// url, err := r.Get("article").URL("subdomain", "news",
// "category", "technology",
// "id", "42")
// // url.String() will be "http://news.domain.com/articles/technology/42"
// url, err := r.Get("article").URL("subdomain", "news",
// "category", "technology",
// "id", "42")
//
// The scheme of the resulting url will be the first argument that was passed to Schemes:
//
// // url.String() will be "https://example.com"
// r := mux.NewRouter()
// url, err := r.Host("example.com")
// .Schemes("https", "http").URL()
// // url.String() will be "https://example.com"
// r := mux.NewRouter().NewRoute()
// url, err := r.Host("example.com")
// .Schemes("https", "http").URL()
//
// All variables defined in the route are required, and their values must
// conform to the corresponding patterns.
@@ -718,6 +728,25 @@ func (r *Route) GetHostTemplate() (string, error) {
return r.regexp.host.template, nil
}

// GetVarNames returns the names of all variables added by regexp matchers
// These can be used to know which route variables should be passed into r.URL()
func (r *Route) GetVarNames() ([]string, error) {
if r.err != nil {
return nil, r.err
}
var varNames []string
if r.regexp.host != nil {
varNames = append(varNames, r.regexp.host.varsN...)
}
if r.regexp.path != nil {
varNames = append(varNames, r.regexp.path.varsN...)
}
for _, regx := range r.regexp.queries {
varNames = append(varNames, regx.varsN...)
}
return varNames, nil
}

// prepareVars converts the route variable pairs into a map. If the route has a
// BuildVarsFunc, it is invoked.
func (r *Route) prepareVars(pairs ...string) (map[string]string, error) {