Full Code of gobuffalo/buffalo for AI

main 0acef9701e38 cached
177 files
366.3 KB
109.8k tokens
849 symbols
1 requests
Download .txt
Showing preview only (402K chars total). Download the full file or copy to clipboard to get everything.
Repository: gobuffalo/buffalo
Branch: main
Commit: 0acef9701e38
Files: 177
Total size: 366.3 KB

Directory structure:
gitextract_pzjmh4ui/

├── .github/
│   ├── CODEOWNERS
│   ├── FUNDING.yml
│   └── workflows/
│       ├── standard-go-test.yml
│       └── standard-stale.yml
├── .gitignore
├── BACKERS.md
├── Dockerfile
├── Dockerfile.build
├── Dockerfile.slim.build
├── LICENSE.txt
├── README.md
├── SECURITY.md
├── SHOULDERS.md
├── app.go
├── app_test.go
├── binding/
│   ├── bindable.go
│   ├── bindable_test.go
│   ├── binding.go
│   ├── binding_test.go
│   ├── decoders/
│   │   ├── decoders.go
│   │   ├── null_time.go
│   │   ├── null_time_test.go
│   │   ├── parse_time.go
│   │   ├── time.go
│   │   └── time_test.go
│   ├── file.go
│   ├── file_request_type_binder.go
│   ├── file_test.go
│   ├── html_content_type_binder.go
│   ├── json_content_type_binder.go
│   ├── request_binder.go
│   ├── request_binder_test.go
│   ├── types.go
│   └── xml_request_type_binder.go
├── buffalo.go
├── context.go
├── cookies.go
├── cookies_test.go
├── default_context.go
├── default_context_test.go
├── errors.go
├── errors_test.go
├── events.go
├── flash.go
├── flash_test.go
├── fs.go
├── fs_test.go
├── go.mod
├── go.sum
├── handler.go
├── home.go
├── internal/
│   ├── defaults/
│   │   ├── defaults.go
│   │   └── defaults_test.go
│   ├── env/
│   │   └── env.go
│   ├── fakesmtp/
│   │   ├── connection.go
│   │   └── server.go
│   ├── httpx/
│   │   ├── content_type.go
│   │   └── content_type_test.go
│   ├── meta/
│   │   ├── meta.go
│   │   └── meta_test.go
│   ├── nulls/
│   │   └── nulls.go
│   ├── templates/
│   │   ├── error.dev.html
│   │   ├── error.prod.html
│   │   └── notfound.prod.html
│   └── testdata/
│       ├── disk/
│       │   ├── file.txt
│       │   ├── file2.txt
│       │   └── under/
│       │       └── sub/
│       │           └── subfile
│       ├── embedded/
│       │   ├── embed.go
│       │   ├── file.txt
│       │   └── under/
│       │       └── sub/
│       │           └── subfile
│       └── panic.txt
├── logger.go
├── mail/
│   ├── README.md
│   ├── attachment.go
│   ├── body.go
│   ├── dialer.go
│   ├── mail.go
│   ├── mail_test.go
│   ├── message.go
│   ├── sender.go
│   ├── smtp_auth.go
│   ├── smtp_errors.go
│   ├── smtp_message.go
│   ├── smtp_mime.go
│   ├── smtp_send.go
│   ├── smtp_sender.go
│   ├── smtp_sender_test.go
│   └── smtp_writeto.go
├── method_override.go
├── method_override_test.go
├── middleware.go
├── middleware_test.go
├── not_found_test.go
├── options.go
├── options_test.go
├── plugins/
│   ├── cache.go
│   ├── command.go
│   ├── decorate.go
│   ├── events.go
│   ├── log.go
│   ├── log_debug.go
│   ├── plugcmds/
│   │   ├── available.go
│   │   ├── available_test.go
│   │   ├── plug_map.go
│   │   └── plug_map_test.go
│   ├── plugdeps/
│   │   ├── command.go
│   │   ├── plugdeps.go
│   │   ├── plugdeps_test.go
│   │   ├── plugin.go
│   │   ├── plugin_test.go
│   │   ├── plugins.go
│   │   ├── plugins_test.go
│   │   └── pop.go
│   ├── plugins.go
│   └── plugins_test.go
├── plugins.go
├── render/
│   ├── auto.go
│   ├── auto_test.go
│   ├── download.go
│   ├── download_test.go
│   ├── func.go
│   ├── func_test.go
│   ├── helpers.go
│   ├── html.go
│   ├── html_test.go
│   ├── js.go
│   ├── js_test.go
│   ├── json.go
│   ├── json_test.go
│   ├── markdown_test.go
│   ├── options.go
│   ├── partials_test.go
│   ├── plain.go
│   ├── plain_test.go
│   ├── render.go
│   ├── render_test.go
│   ├── renderer.go
│   ├── sse.go
│   ├── string.go
│   ├── string_map.go
│   ├── string_map_test.go
│   ├── string_test.go
│   ├── template.go
│   ├── template_engine.go
│   ├── template_helpers.go
│   ├── template_helpers_test.go
│   ├── template_test.go
│   ├── xml.go
│   └── xml_test.go
├── request_data.go
├── request_data_test.go
├── request_logger.go
├── resource.go
├── response.go
├── response_test.go
├── route.go
├── route_info.go
├── route_info_test.go
├── route_mappings.go
├── route_mappings_test.go
├── routenamer.go
├── router_test.go
├── runtime/
│   └── build.go
├── server.go
├── server_test.go
├── servers/
│   ├── listener.go
│   ├── servers.go
│   ├── simple.go
│   └── tls.go
├── session.go
├── session_test.go
├── worker/
│   ├── job.go
│   ├── simple.go
│   ├── simple_test.go
│   └── worker.go
├── wrappers.go
└── wrappers_test.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/CODEOWNERS
================================================
# Default owner
*       @gobuffalo/core-managers

================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: markbates
patreon: buffalo


================================================
FILE: .github/workflows/standard-go-test.yml
================================================
name: Standard Test

on:
  push:
    branches: [main v1]
  pull_request:

permissions:
  contents: read

jobs:
  call-standard-test:
    name: Test
    uses: gobuffalo/.github/.github/workflows/go-test.yml@v1.8
    secrets: inherit

  govulncheck:
    name: govulncheck
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: "1.26"

      - name: Install govulncheck
        run: go install golang.org/x/vuln/cmd/govulncheck@latest

      - name: Run govulncheck
        run: govulncheck ./...


================================================
FILE: .github/workflows/standard-stale.yml
================================================
name: Standard Autocloser

on:
  schedule:
    - cron: "30 1 * * *"

jobs:
  call-standard-autocloser:
    name: Autocloser
    uses: gobuffalo/.github/.github/workflows/stale.yml@v1
    secrets: inherit


================================================
FILE: .gitignore
================================================
*.log
.DS_Store
doc
tmp
pkg
*.gem
*.pid
coverage
coverage.data
*.pbxuser
*.mode1v3
.svn
profile
.console_history
.sass-cache/*
.rake_tasks~
*.log.lck
solr/
.jhw-cache/
jhw.*
*.sublime*
node_modules/
dist/
generated/
.vendor/
bin/*
gin-bin
.idea/
.vscode/settings.json


================================================
FILE: BACKERS.md
================================================
# Financial Backers of the Buffalo Project

Buffalo is a community-driven project that is run by individuals who believe that Buffalo is the way to quickly, and easily, build high quality, scalable applications in Go.

Financial contributions to the Buffalo go towards ongoing development costs, servers, swag, conferences, etc...

If you, or your company, use Buffalo, please consider supporting this effort to make rapid web development in Go, simple, easy, and fun!

[http://patreon.com/buffalo](http://patreon.com/buffalo)

---

## Platinum Sponsors

* **[Gopher Guides](https://www.gopherguides.com)**
* **[PaperCall.io](https://www.papercall.io)**
* **[Wawandco](https://wawand.co)**
* **[Symbolsecurity](https://symbolsecurity.com)**
* [Your Company Here](http://patreon.com/buffalo)

### Gold Sponsors

* [Your Company Here](http://patreon.com/buffalo)

### Premium Backers

* [Your Company Here](http://patreon.com/buffalo)

#### Generous Backers

* **[Zhorty](https://zhorty.com)**
* [Your Company Here](http://patreon.com/buffalo)



================================================
FILE: Dockerfile
================================================
FROM gobuffalo/buffalo:latest

ARG CODECOV_TOKEN

ENV GOPROXY         https://proxy.golang.org
ENV BP              /src/buffalo

RUN rm -rf $BP
RUN mkdir -p $BP

WORKDIR $BP
COPY . .

RUN go mod tidy
RUN go test -tags "sqlite integration_test" -cover -race -v ./...


================================================
FILE: Dockerfile.build
================================================
FROM golang:1.17

EXPOSE 3000

ENV GOPROXY=https://proxy.golang.org

RUN apt-get update \
    && apt-get install -y -q build-essential sqlite3 libsqlite3-dev postgresql libpq-dev vim

# Installing Node 12
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash 
RUN apt-get update && apt-get install nodejs

# Installing Postgres
RUN sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" >> /etc/apt/sources.list.d/pgdg.list' \
    && wget -q https://www.postgresql.org/media/keys/ACCC4CF8.asc -O - | apt-key add - \
    && apt-get update \
    && apt-get install -y -q postgresql postgresql-contrib libpq-dev\
    && rm -rf /var/lib/apt/lists/* \
    && service postgresql start && \
    # Setting up password for postgres
    su -c "psql -c \"ALTER USER postgres  WITH PASSWORD 'postgres';\"" - postgres

# Installing yarn
RUN npm install -g --no-progress yarn \
    && yarn config set yarn-offline-mirror /npm-packages-offline-cache \
    && yarn config set yarn-offline-mirror-pruning true

# Install golangci
RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.24.0
# Installing buffalo binary
RUN go install github.com/gobuffalo/cli/cmd/buffalo@latest
RUN go get github.com/gobuffalo/buffalo-pop/v2

RUN mkdir /src
WORKDIR /src


================================================
FILE: Dockerfile.slim.build
================================================
FROM golang:1.17-alpine

EXPOSE 3000

ENV GOPROXY=https://proxy.golang.org 

RUN apk add --no-cache --upgrade apk-tools \
    && apk add --no-cache bash curl openssl git build-base nodejs npm sqlite sqlite-dev mysql-client vim postgresql libpq postgresql-contrib libc6-compat

# Installing linter
RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh \
    | sh -s -- -b $(go env GOPATH)/bin v1.24.0

# Installing Yarn
RUN npm i -g --no-progress yarn \
    && yarn config set yarn-offline-mirror /npm-packages-offline-cache \
    && yarn config set yarn-offline-mirror-pruning true

# Installing buffalo binary
RUN go install github.com/gobuffalo/cli/cmd/buffalo@latest
RUN go get github.com/gobuffalo/buffalo-pop/v2

RUN mkdir /src
WORKDIR /src


================================================
FILE: LICENSE.txt
================================================
The MIT License (MIT)
Copyright (c) 2016 Mark Bates

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
<p align="center"><img src="https://raw.githubusercontent.com/gobuffalo/buffalo/master/logo.svg" width="360"></p>

<p align="center">
<a href="https://pkg.go.dev/github.com/gobuffalo/buffalo"><img src="https://pkg.go.dev/badge/github.com/gobuffalo/buffalo" alt="PkgGoDev"></a>
<a href="https://github.com/gobuffalo/buffalo/actions/workflows/standard-go-test.yml"><img src="https://github.com/gobuffalo/buffalo/actions/workflows/standard-go-test.yml/badge.svg"></a>
<a href="https://goreportcard.com/report/github.com/gobuffalo/buffalo"><img src="https://goreportcard.com/badge/github.com/gobuffalo/buffalo" alt="Go Report Card" /></a>
<a href="https://www.codetriage.com/gobuffalo/buffalo"><img src="https://www.codetriage.com/gobuffalo/buffalo/badges/users.svg" alt="Open Source Helpers" /></a>
</p>

# Buffalo

A Go web development eco-system, designed to make your project easier.

Buffalo helps you to generate a web project that already has everything from front-end (JavaScript, SCSS, etc.) to the back-end (database, routing, etc.) already hooked up and ready to run. From there it provides easy APIs to build your web application quickly in Go.

Buffalo **isn't just a framework**; it's a holistic web development environment and project structure that **lets developers get straight to the business** of, well, building their business.

> I :heart: web dev in go again - Brian Ketelsen

## Versions

The current stable version of Buffalo core is v1 (`v1` branch).

Versions (branches):
* `main` is for the current mainstream development.
* `v1` is the current stable release.

## ⚠️ Important

Buffalo works only with Go [modules](https://blog.golang.org/using-go-modules). `GOPATH` mode is likely to break most of the functionality of the Buffalo eco-system. Please see [this blog post](https://blog.gobuffalo.io/the-road-to-1-0-requiring-modules-5672c6b015e5) for more information.

Also, the Buffalo team actively gives support to the last 2 versions of Go, which at the moment are Go 1.23 and 1.24. While Buffalo `may` work on older versions, we encourage you to upgrade to latest 2 versions of Go for a better development experience.

## Documentation

Please visit [http://gobuffalo.io](http://gobuffalo.io) for the latest documentation, examples, and more.

### Quick Start

- [Installation](https://gobuffalo.io/documentation/getting_started/installation)
- [Create a new project](https://gobuffalo.io/documentation/getting_started/new-project)
- [Tutorials](https://gobuffalo.io/documentation/tutorials/)

## Shoulders of Giants

Buffalo would not be possible if not for all of the great projects it depends on. Please see [SHOULDERS.md](SHOULDERS.md) to see a list of them.

### Templating

[github.com/gobuffalo/plush](https://github.com/gobuffalo/plush) - This templating package was chosen over the standard Go `html/template` package for a variety of reasons. The biggest of which is that it is significantly more flexible and easy to work with.

### Routing

[github.com/gorilla/mux](https://github.com/gorilla/mux) - This router was chosen because of its stability and flexibility. There might be faster routers out there, but this one is definitely the most powerful!

### Models/ORM (Optional)

[github.com/gobuffalo/pop](https://github.com/gobuffalo/pop) - Accessing databases is nothing new in web applications. Pop, and its command line tool, Soda, were chosen because they strike a nice balance between simplifying common tasks, being idiomatic, and giving you the flexibility you need to build your app. Pop and Soda share the same core philosophies as Buffalo, so they were a natural choice.

### Sessions, Cookies, WebSockets, and more

[github.com/gorilla](https://github.com/gorilla) - The Gorilla toolkit is a great set of packages designed to improve upon the standard library for a variety of web-related packages. With these high-quality packages Buffalo can keep its "core" code to a minimum and focus on its goal of gluing them all together to make your life better.

## Benchmarks

Oh, yeah, everyone wants benchmarks! What would a web framework be without its benchmarks? Well, guess what? I'm not giving you any! That's right. This is Go! I assure you that it is plenty fast enough for you. If you want benchmarks you can either a) check out any benchmarks that the [GIANTS](SHOULDERS.md) Buffalo is built upon having published, or b) run your own. I have no interest in playing the benchmark game, and neither should you.

## Contributing

First, thank you so much for wanting to contribute! It means so much that you care enough to want to contribute. We appreciate every PR from the smallest of typos to the be biggest of features.

**Here are the core rules to respect**:

- If you have any question, please consider using the
  [Slack channel](https://gophers.slack.com/messages/buffalo/) (-#buffalo-,
  *#buffalo_fr* or *#buffalo-dev* for contribution related questions) or
  [Stack Overflow](https://stackoverflow.com/questions/tagged/buffalo).
  We use GitHub issues for **bug reports and feature requests only**.
- All contributors of this project are working on their free time: be patient
  and kind. :-
- Consider opening an issue **BEFORE** creating a Pull request (PR): you won't
  lose your time on fixing non-existing bugs, or fixing the wrong bug. Also we
  can help you to produce the best PR!
- Open a PR against the `main` branch if your PR is for mainstream or version
  specific branch e.g. `v1` if your PR is for specific version.
  Note that the valid branch for a new feature request PR should be `main`
  while a PR against a version specific branch are allowed only for bugfixes.

For the full contribution guidelines, please read [CONTRIBUTING](.github/CONTRIBUTING.md).


================================================
FILE: SECURITY.md
================================================
# Security Policy

## Supported Versions

| Version | Supported          |
| ------- | ------------------ |
| 1.x.x   | :white_check_mark: |

## Reporting a Vulnerability

Contact @paganotoni or @sio4 on the [Gophers Slack](https://gophers.slack.com).


================================================
FILE: SHOULDERS.md
================================================
# Buffalo Stands on the Shoulders of Giants

Buffalo does not try to reinvent the wheel! Instead, it uses the already great wheels developed by the Go community and puts them all together in the best way possible. Without these giants, this project would not be possible. Please make sure to check them out and thank them for all of their hard work.

Thank you to the following **GIANTS**:

* [github.com/BurntSushi/toml](https://godoc.org/github.com/BurntSushi/toml)
* [github.com/aymerick/douceur](https://godoc.org/github.com/aymerick/douceur)
* [github.com/cpuguy83/go-md2man/v2](https://godoc.org/github.com/cpuguy83/go-md2man/v2)
* [github.com/davecgh/go-spew](https://godoc.org/github.com/davecgh/go-spew)
* [github.com/dustin/go-humanize](https://godoc.org/github.com/dustin/go-humanize)
* [github.com/fatih/color](https://godoc.org/github.com/fatih/color)
* [github.com/fatih/structs](https://godoc.org/github.com/fatih/structs)
* [github.com/felixge/httpsnoop](https://godoc.org/github.com/felixge/httpsnoop)
* [github.com/fsnotify/fsnotify](https://godoc.org/github.com/fsnotify/fsnotify)
* [github.com/go-sql-driver/mysql](https://godoc.org/github.com/go-sql-driver/mysql)
* [github.com/joho/godotenv](https://godoc.org/github.com/joho/godotenv)
* [github.com/gobuffalo/events](https://godoc.org/github.com/gobuffalo/events)
* [github.com/gobuffalo/flect](https://godoc.org/github.com/gobuffalo/flect)
* [github.com/gobuffalo/github_flavored_markdown](https://godoc.org/github.com/gobuffalo/github_flavored_markdown)
* [github.com/gobuffalo/helpers](https://godoc.org/github.com/gobuffalo/helpers)
* [github.com/gobuffalo/here](https://godoc.org/github.com/gobuffalo/here)
* [github.com/gobuffalo/httptest](https://godoc.org/github.com/gobuffalo/httptest)
* [github.com/gobuffalo/logger](https://godoc.org/github.com/gobuffalo/logger)
* [github.com/gobuffalo/meta](https://godoc.org/github.com/gobuffalo/meta)
* [github.com/gobuffalo/nulls](https://godoc.org/github.com/gobuffalo/nulls)
* [github.com/gobuffalo/plush/v5](https://godoc.org/github.com/gobuffalo/plush/v5)
* [github.com/gobuffalo/refresh](https://godoc.org/github.com/gobuffalo/refresh)
* [github.com/gobuffalo/tags/v3](https://godoc.org/github.com/gobuffalo/tags/v3)
* [github.com/gobuffalo/validate/v3](https://godoc.org/github.com/gobuffalo/validate/v3)
* [github.com/gofrs/uuid](https://godoc.org/github.com/gofrs/uuid)
* [github.com/google/go-cmp](https://godoc.org/github.com/google/go-cmp)
* [github.com/gorilla/css](https://godoc.org/github.com/gorilla/css)
* [github.com/gorilla/handlers](https://godoc.org/github.com/gorilla/handlers)
* [github.com/gorilla/mux](https://godoc.org/github.com/gorilla/mux)
* [github.com/gorilla/securecookie](https://godoc.org/github.com/gorilla/securecookie)
* [github.com/gorilla/sessions](https://godoc.org/github.com/gorilla/sessions)
* [github.com/inconshreveable/mousetrap](https://godoc.org/github.com/inconshreveable/mousetrap)
* [github.com/jmoiron/sqlx](https://godoc.org/github.com/jmoiron/sqlx)
* [github.com/joho/godotenv](https://godoc.org/github.com/joho/godotenv)
* [github.com/kr/pretty](https://godoc.org/github.com/kr/pretty)
* [github.com/kr/pty](https://godoc.org/github.com/kr/pty)
* [github.com/kr/text](https://godoc.org/github.com/kr/text)
* [github.com/lib/pq](https://godoc.org/github.com/lib/pq)
* [github.com/mattn/go-colorable](https://godoc.org/github.com/mattn/go-colorable)
* [github.com/mattn/go-isatty](https://godoc.org/github.com/mattn/go-isatty)
* [github.com/mattn/go-sqlite3](https://godoc.org/github.com/mattn/go-sqlite3)
* [github.com/microcosm-cc/bluemonday](https://godoc.org/github.com/microcosm-cc/bluemonday)
* [github.com/mitchellh/go-homedir](https://godoc.org/github.com/mitchellh/go-homedir)
* [github.com/monoculum/formam](https://godoc.org/github.com/monoculum/formam)
* [github.com/pkg/diff](https://godoc.org/github.com/pkg/diff)
* [github.com/pmezard/go-difflib](https://godoc.org/github.com/pmezard/go-difflib)
* [github.com/psanford/memfs](https://godoc.org/github.com/psanford/memfs)
* [github.com/rogpeppe/go-internal](https://godoc.org/github.com/rogpeppe/go-internal)
* [github.com/russross/blackfriday/v2](https://godoc.org/github.com/russross/blackfriday/v2)
* [github.com/sergi/go-diff](https://godoc.org/github.com/sergi/go-diff)
* [github.com/sirupsen/logrus](https://godoc.org/github.com/sirupsen/logrus)
* [github.com/sourcegraph/annotate](https://godoc.org/github.com/sourcegraph/annotate)
* [github.com/sourcegraph/syntaxhighlight](https://godoc.org/github.com/sourcegraph/syntaxhighlight)
* [github.com/spf13/cobra](https://godoc.org/github.com/spf13/cobra)
* [github.com/spf13/pflag](https://godoc.org/github.com/spf13/pflag)
* [github.com/stretchr/objx](https://godoc.org/github.com/stretchr/objx)
* [github.com/stretchr/testify](https://godoc.org/github.com/stretchr/testify)
* [github.com/yuin/goldmark](https://godoc.org/github.com/yuin/goldmark)
* [golang.org/x/crypto](https://godoc.org/golang.org/x/crypto)
* [golang.org/x/mod](https://godoc.org/golang.org/x/mod)
* [golang.org/x/net](https://godoc.org/golang.org/x/net)
* [golang.org/x/sync](https://godoc.org/golang.org/x/sync)
* [golang.org/x/sys](https://godoc.org/golang.org/x/sys)
* [golang.org/x/term](https://godoc.org/golang.org/x/term)
* [golang.org/x/text](https://godoc.org/golang.org/x/text)
* [golang.org/x/tools](https://godoc.org/golang.org/x/tools)
* [golang.org/x/xerrors](https://godoc.org/golang.org/x/xerrors)
* [gopkg.in/check.v1](https://godoc.org/gopkg.in/check.v1)
* [gopkg.in/yaml.v2](https://godoc.org/gopkg.in/yaml.v2)
* [gopkg.in/yaml.v3](https://godoc.org/gopkg.in/yaml.v3)


================================================
FILE: app.go
================================================
package buffalo

import (
	"fmt"
	"net/http"
	"sync"

	"github.com/gobuffalo/buffalo/internal/env"
	"github.com/gorilla/mux"
)

// App is where it all happens! It holds on to options,
// the underlying router, the middleware, and more.
// Without an App you can't do much!
type App struct {
	Options
	// Middleware, ErrorHandlers, router, and filepaths are moved to Home.
	Home
	moot   *sync.RWMutex
	routes RouteList
	// TODO: to be deprecated #road-to-v1
	root     *App
	children []*App

	// Routenamer for the app. This field provides the ability to override the
	// base route namer for something more specific to the app.
	RouteNamer RouteNamer
}

// Muxer returns the underlying mux router to allow
// for advance configurations
func (a *App) Muxer() *mux.Router {
	return a.router
}

// New returns a new instance of App and adds some sane, and useful, defaults.
func New(opts Options) *App {
	LoadPlugins()
	env.Load()

	opts = optionsWithDefaults(opts)

	a := &App{
		Options: opts,
		Home: Home{
			name:   opts.Name,
			host:   opts.Host,
			prefix: opts.Prefix,
			ErrorHandlers: ErrorHandlers{
				http.StatusNotFound:            defaultErrorHandler,
				http.StatusInternalServerError: defaultErrorHandler,
			},
			router: mux.NewRouter(),
		},
		moot:     &sync.RWMutex{},
		routes:   RouteList{},
		children: []*App{},

		RouteNamer: baseRouteNamer{},
	}
	a.Home.app = a     // replace root.
	a.Home.appSelf = a // temporary, reverse reference to the group app.

	notFoundHandler := func(errorf string, code int) http.HandlerFunc {
		return func(res http.ResponseWriter, req *http.Request) {
			c := a.newContext(RouteInfo{}, res, req)
			err := fmt.Errorf(errorf, req.Method, req.URL.Path)
			_ = a.ErrorHandlers.Get(code)(code, err, c)
		}
	}

	a.router.NotFoundHandler = notFoundHandler("path not found: %s %s", http.StatusNotFound)
	a.router.MethodNotAllowedHandler = notFoundHandler("method not found: %s %s", http.StatusMethodNotAllowed)

	if a.MethodOverride == nil {
		a.MethodOverride = MethodOverride
	}

	a.Middleware = newMiddlewareStack(RequestLogger)
	a.Use(a.defaultErrorMiddleware)
	a.Use(a.PanicHandler)

	return a
}


================================================
FILE: app_test.go
================================================
package buffalo

func voidHandler(c Context) error {
	return nil
}


================================================
FILE: binding/bindable.go
================================================
package binding

import "net/http"

// Bindable when implemented, on a type
// will override any Binders that have been
// configured when using buffalo#Context.Bind
type Bindable interface {
	Bind(*http.Request) error
}


================================================
FILE: binding/bindable_test.go
================================================
package binding

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/require"
)

type orbison struct {
	bound bool
}

func (o *orbison) Bind(req *http.Request) error {
	o.bound = true
	return nil
}

func Test_Bindable(t *testing.T) {
	r := require.New(t)

	req := httptest.NewRequest("GET", "/", nil)
	o := &orbison{}
	r.False(o.bound)
	r.NoError(Exec(req, o))
	r.True(o.bound)
}


================================================
FILE: binding/binding.go
================================================
package binding

import (
	"net/http"
	"time"

	"github.com/gobuffalo/buffalo/binding/decoders"
	"github.com/gobuffalo/buffalo/internal/nulls"
	"github.com/monoculum/formam"
)

var (
	// MaxFileMemory can be used to set the maximum size, in bytes, for files to be
	// stored in memory during uploaded for multipart requests.
	// See https://golang.org/pkg/net/http/#Request.ParseMultipartForm for more
	// information on how this impacts file uploads.
	MaxFileMemory int64 = 5 * 1024 * 1024

	// formDecoder (formam) that will be used across ContentTypeBinders
	formDecoder = buildFormDecoder()

	// BaseRequestBinder is an instance of the requestBinder, it comes with preconfigured
	// content type binders for HTML, JSON, XML and Files, as well as custom types decoders
	// for time.Time and nulls.Time
	BaseRequestBinder = NewRequestBinder(
		HTMLContentTypeBinder{
			decoder: formDecoder,
		},
		JSONContentTypeBinder{},
		XMLRequestTypeBinder{},
		FileRequestTypeBinder{
			decoder: formDecoder,
		},
	)
)

// buildFormDecoder that will be used in the package. This method adds some custom decoders for time.Time and nulls.Time.
func buildFormDecoder() *formam.Decoder {
	decoder := formam.NewDecoder(&formam.DecoderOptions{
		TagName:           "form",
		IgnoreUnknownKeys: true,
	})

	decoder.RegisterCustomType(decoders.TimeDecoderFn(), []any{time.Time{}}, nil)
	decoder.RegisterCustomType(decoders.NullTimeDecoderFn(), []any{nulls.Time{}}, nil)

	return decoder
}

// RegisterTimeFormats allows to add custom time layouts that
// the binder will be able to use for decoding.
func RegisterTimeFormats(layouts ...string) {
	decoders.RegisterTimeFormats(layouts...)
}

// RegisterCustomDecoder allows to define custom decoders for certain types
// In the request.
func RegisterCustomDecoder(fn CustomTypeDecoder, types []any, fields []any) {
	rawFunc := (func([]string) (any, error))(fn)
	formDecoder.RegisterCustomType(rawFunc, types, fields)
}

// Register maps a request Content-Type (application/json)
// to a Binder.
func Register(contentType string, fn Binder) {
	BaseRequestBinder.Register(contentType, fn)
}

// Exec will bind the interface to the request.Body. The type of binding
// is dependent on the "Content-Type" for the request. If the type
// is "application/json" it will use "json.NewDecoder". If the type
// is "application/xml" it will use "xml.NewDecoder". The default
// binder is "https://github.com/monoculum/formam".
func Exec(req *http.Request, value any) error {
	return BaseRequestBinder.Exec(req, value)
}


================================================
FILE: binding/binding_test.go
================================================
package binding

import (
	"net/http"
	"net/url"
	"testing"

	"github.com/stretchr/testify/require"
)

type blogPost struct {
	Tags     []string
	Dislikes int
	Likes    int32
}

func Test_Register(t *testing.T) {
	r := require.New(t)

	Register("foo/bar", func(*http.Request, any) error {
		return nil
	})

	r.NotNil(BaseRequestBinder.binders["foo/bar"])

	req, err := http.NewRequest("POST", "/", nil)
	r.NoError(err)

	req.Header.Set("Content-Type", "foo/bar")
	req.Form = url.Values{
		"Tags":     []string{"AAA"},
		"Likes":    []string{"12"},
		"Dislikes": []string{"1000"},
	}

	req.ParseForm()

	var post blogPost
	r.NoError(Exec(req, &post))

	r.Equal([]string(nil), post.Tags)
	r.Equal(int32(0), post.Likes)
	r.Equal(0, post.Dislikes)

}

func Test_RegisterCustomDecoder(t *testing.T) {
	r := require.New(t)

	RegisterCustomDecoder(func(vals []string) (any, error) {
		return []string{"X"}, nil
	}, []any{[]string{}}, nil)

	RegisterCustomDecoder(func(vals []string) (any, error) {
		return 0, nil
	}, []any{int(0)}, nil)

	post := blogPost{}
	req, err := http.NewRequest("POST", "/", nil)
	r.NoError(err)

	req.Header.Set("Content-Type", "application/html")
	req.Form = url.Values{
		"Tags":     []string{"AAA"},
		"Likes":    []string{"12"},
		"Dislikes": []string{"1000"},
	}
	req.ParseForm()

	r.NoError(Exec(req, &post))
	r.Equal([]string{"X"}, post.Tags)
	r.Equal(int32(12), post.Likes)
	r.Equal(0, post.Dislikes)
}


================================================
FILE: binding/decoders/decoders.go
================================================
package decoders

import (
	"sync"
	"time"
)

var (
	lock = &sync.RWMutex{}

	// timeFormats are the base time formats supported by the time.Time and
	// nulls.Time Decoders you can prepend custom formats to this list
	// by using RegisterTimeFormats.
	timeFormats = []string{
		time.RFC3339,
		"01/02/2006",
		"2006-01-02",
		"2006-01-02T15:04",
		time.ANSIC,
		time.UnixDate,
		time.RubyDate,
		time.RFC822,
		time.RFC822Z,
		time.RFC850,
		time.RFC1123,
		time.RFC1123Z,
		time.RFC3339Nano,
		time.Kitchen,
		time.Stamp,
		time.StampMilli,
		time.StampMicro,
		time.StampNano,
	}
)

// RegisterTimeFormats allows to add custom time layouts that
// the binder will be able to use for decoding.
func RegisterTimeFormats(layouts ...string) {
	lock.Lock()
	defer lock.Unlock()

	timeFormats = append(layouts, timeFormats...)
}


================================================
FILE: binding/decoders/null_time.go
================================================
package decoders

import "github.com/gobuffalo/buffalo/internal/nulls"

// NullTimeDecoderFn is a custom type decoder func for null.Time fields
func NullTimeDecoderFn() func([]string) (any, error) {
	return func(vals []string) (any, error) {
		var ti nulls.Time

		// If vals is empty, return a nulls.Time with Valid = false (i.e. NULL).
		// The parseTime() function called below does this check as well, but
		// because it doesn't return an error in the case where vals is empty,
		// we have no way to determine from its response that the nulls.Time
		// should actually be NULL.
		if len(vals) == 0 || vals[0] == "" {
			return ti, nil
		}

		t, err := parseTime(vals)
		if err != nil {
			return ti, err
		}

		ti.Time = t
		ti.Valid = true

		return ti, nil
	}
}


================================================
FILE: binding/decoders/null_time_test.go
================================================
package decoders

import (
	"testing"
	"time"

	"github.com/gobuffalo/buffalo/internal/nulls"
	"github.com/stretchr/testify/require"
)

func Test_NullTimeCustomDecoder_Decode(t *testing.T) {
	r := require.New(t)

	testCases := []struct {
		input     string
		expected  time.Time
		expValid  bool
		expectErr bool
	}{
		{
			input:    "2017-01-01",
			expected: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
			expValid: true,
		},
		{
			input:    "2018-07-13T15:34",
			expected: time.Date(2018, time.July, 13, 15, 34, 0, 0, time.UTC),
			expValid: true,
		},
		{
			input:    "2018-20-10T30:15",
			expected: time.Time{},
			expValid: false,
		},
		{
			input:    "",
			expected: time.Time{},
			expValid: false,
		},
	}

	for _, testCase := range testCases {

		tt, err := NullTimeDecoderFn()([]string{testCase.input})
		r.IsType(tt, nulls.Time{})
		nt := tt.(nulls.Time)

		if testCase.expectErr {
			r.Error(err)
			r.Equal(nt.Valid, false)
			continue
		}

		r.Equal(testCase.expected, nt.Time)
		r.Equal(testCase.expValid, nt.Valid)
	}
}


================================================
FILE: binding/decoders/parse_time.go
================================================
package decoders

import (
	"time"
)

func parseTime(vals []string) (time.Time, error) {
	var t time.Time
	var err error

	// don't try to parse empty time values, it will raise an error
	if len(vals) == 0 || vals[0] == "" {
		return t, nil
	}

	for _, layout := range timeFormats {
		t, err = time.Parse(layout, vals[0])
		if err == nil {
			return t, nil
		}
	}

	if err != nil {
		return t, err
	}

	return t, nil
}


================================================
FILE: binding/decoders/time.go
================================================
package decoders

// TimeDecoderFn is a custom type decoder func for Time fields
func TimeDecoderFn() func([]string) (any, error) {
	return func(vals []string) (any, error) {
		return parseTime(vals)
	}
}


================================================
FILE: binding/decoders/time_test.go
================================================
package decoders

import (
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func TestParseTimeErrorParsing(t *testing.T) {
	r := require.New(t)

	_, err := parseTime([]string{"this is sparta"})
	r.Error(err)
}

func TestParseTime(t *testing.T) {
	r := require.New(t)

	testCases := []struct {
		input     string
		expected  time.Time
		expectErr bool
	}{
		{
			input:     "2017-01-01",
			expected:  time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
			expectErr: false,
		},
		{
			input:     "2018-07-13T15:34",
			expected:  time.Date(2018, time.July, 13, 15, 34, 0, 0, time.UTC),
			expectErr: false,
		},
		{
			input:     "2018-20-10T30:15",
			expected:  time.Time{},
			expectErr: true,
		},
	}

	for _, tc := range testCases {
		tt, err := parseTime([]string{tc.input})
		if !tc.expectErr {
			r.NoError(err)
		}

		r.Equal(tc.expected, tt)
	}
}

func TestParseTimeConflicting(t *testing.T) {
	r := require.New(t)

	RegisterTimeFormats("2006-02-01")
	tt, err := parseTime([]string{"2017-01-10"})

	r.NoError(err)
	expected := time.Date(2017, time.October, 1, 0, 0, 0, 0, time.UTC)
	r.Equal(expected, tt)
}


================================================
FILE: binding/file.go
================================================
package binding

import (
	"mime/multipart"
)

// File holds information regarding an uploaded file
type File struct {
	multipart.File
	*multipart.FileHeader
}

// Valid if there is an actual uploaded file
func (f File) Valid() bool {
	return f.File != nil
}

func (f File) String() string {
	if f.File == nil {
		return ""
	}
	return f.Filename
}


================================================
FILE: binding/file_request_type_binder.go
================================================
package binding

import (
	"net/http"
	"reflect"

	"github.com/monoculum/formam"
)

// FileRequestTypeBinder is in charge of binding File request types.
type FileRequestTypeBinder struct {
	decoder *formam.Decoder
}

// ContentTypes returns the list of content types for FileRequestTypeBinder
func (ht FileRequestTypeBinder) ContentTypes() []string {
	return []string{
		"multipart/form-data",
	}
}

// BinderFunc that will take care of the HTML File binding
func (ht FileRequestTypeBinder) BinderFunc() Binder {
	return func(req *http.Request, i any) error {
		err := req.ParseMultipartForm(MaxFileMemory)
		if err != nil {
			return err
		}

		if err := ht.decoder.Decode(req.Form, i); err != nil {
			return err
		}

		form := req.MultipartForm.File
		if len(form) == 0 {
			return nil
		}

		ri := reflect.Indirect(reflect.ValueOf(i))
		rt := ri.Type()
		for n := range form {
			f := ri.FieldByName(n)
			if !f.IsValid() {
				for i := 0; i < rt.NumField(); i++ {
					sf := rt.Field(i)
					if sf.Tag.Get("form") == n {
						f = ri.Field(i)
						break
					}
				}
			}
			if !f.IsValid() {
				continue
			}
			if f.Kind() == reflect.Slice {
				for _, fh := range req.MultipartForm.File[n] {
					mf, err := fh.Open()
					if err != nil {
						return err
					}

					f.Set(reflect.Append(f, reflect.ValueOf(File{
						File:       mf,
						FileHeader: fh,
					})))
				}
				continue
			}
			if _, ok := f.Interface().(File); ok {
				mf, mh, err := req.FormFile(n)
				if err != nil {
					return err
				}
				f.Set(reflect.ValueOf(File{
					File:       mf,
					FileHeader: mh,
				}))
			}
		}

		return nil
	}
}


================================================
FILE: binding/file_test.go
================================================
package binding_test

import (
	"bytes"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/gobuffalo/buffalo"
	"github.com/gobuffalo/buffalo/binding"
	"github.com/gobuffalo/buffalo/render"
	"github.com/stretchr/testify/require"
)

type WithFile struct {
	MyFile binding.File
}

type NamedFileSlice struct {
	MyFiles []binding.File `form:"thefiles"`
}

type NamedFile struct {
	MyFile binding.File `form:"afile"`
}

func App() *buffalo.App {
	a := buffalo.New(buffalo.Options{})
	a.POST("/on-struct", func(c buffalo.Context) error {
		wf := &WithFile{}
		if err := c.Bind(wf); err != nil {
			return err
		}
		return c.Render(http.StatusCreated, render.String(wf.MyFile.Filename))
	})
	a.POST("/named-file", func(c buffalo.Context) error {
		wf := &NamedFile{}
		if err := c.Bind(wf); err != nil {
			return err
		}
		return c.Render(http.StatusCreated, render.String(wf.MyFile.Filename))
	})
	a.POST("/named-file-slice", func(c buffalo.Context) error {
		wmf := &NamedFileSlice{}
		if err := c.Bind(wmf); err != nil {
			return err
		}
		result := make([]string, len(wmf.MyFiles))
		for i, f := range wmf.MyFiles {
			result[i] += fmt.Sprintf("%s", f.Filename)

		}
		return c.Render(http.StatusCreated, render.String(strings.Join(result, ",")))
	})
	a.POST("/on-context", func(c buffalo.Context) error {
		f, err := c.File("MyFile")
		if err != nil {
			return err
		}
		return c.Render(http.StatusCreated, render.String(f.Filename))
	})

	return a
}

func Test_File_Upload_On_Struct(t *testing.T) {
	r := require.New(t)

	req, err := newFileUploadRequest("/on-struct", "MyFile", "file_test.go")
	r.NoError(err)
	res := httptest.NewRecorder()

	App().ServeHTTP(res, req)

	r.Equal(http.StatusCreated, res.Code)
	r.Equal("file_test.go", res.Body.String())
}

func Test_File_Upload_On_Struct_WithTag_WithMultipleFiles(t *testing.T) {
	r := require.New(t)

	req, err := newFileUploadRequest("/named-file-slice", "thefiles", "file_test.go", "file.go", "types.go")
	r.NoError(err)
	res := httptest.NewRecorder()

	App().ServeHTTP(res, req)

	r.Equal(http.StatusCreated, res.Code)
	r.Equal("file_test.go,file.go,types.go", res.Body.String())
}

func Test_File_Upload_On_Struct_WithTag(t *testing.T) {
	r := require.New(t)

	req, err := newFileUploadRequest("/named-file", "afile", "file_test.go")
	r.NoError(err)
	res := httptest.NewRecorder()

	App().ServeHTTP(res, req)

	r.Equal(http.StatusCreated, res.Code)
	r.Equal("file_test.go", res.Body.String())
}

func Test_File_Upload_On_Context(t *testing.T) {
	r := require.New(t)

	req, err := newFileUploadRequest("/on-context", "MyFile", "file_test.go")
	r.NoError(err)
	res := httptest.NewRecorder()

	App().ServeHTTP(res, req)

	r.Equal(http.StatusCreated, res.Code)
	r.Equal("file_test.go", res.Body.String())
}

// this helper method was inspired by this blog post by Matt Aimonetti:
// https://matt.aimonetti.net/posts/2013/07/01/golang-multipart-file-upload-example/
func newFileUploadRequest(uri string, paramName string, paths ...string) (*http.Request, error) {
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	for _, path := range paths {
		file, err := os.Open(path)
		if err != nil {
			return nil, err
		}
		defer file.Close()
		part, err := writer.CreateFormFile(paramName, filepath.Base(path))
		if err != nil {
			return nil, err
		}
		if _, err = io.Copy(part, file); err != nil {
			return nil, err
		}
	}

	if err := writer.Close(); err != nil {
		return nil, err
	}
	req, err := http.NewRequest("POST", uri, body)
	req.Header.Set("Content-Type", writer.FormDataContentType())
	return req, err
}


================================================
FILE: binding/html_content_type_binder.go
================================================
package binding

import (
	"net/http"

	"github.com/monoculum/formam"
)

// HTMLContentTypeBinder is in charge of binding HTML request types.
type HTMLContentTypeBinder struct {
	decoder *formam.Decoder
}

// ContentTypes that will be used to identify HTML requests
func (ht HTMLContentTypeBinder) ContentTypes() []string {
	return []string{
		"application/html",
		"text/html",
		"application/x-www-form-urlencoded",
		"html",
	}
}

// BinderFunc that will take care of the HTML binding
func (ht HTMLContentTypeBinder) BinderFunc() Binder {
	return func(req *http.Request, i any) error {
		err := req.ParseForm()
		if err != nil {
			return err
		}

		if err := ht.decoder.Decode(req.Form, i); err != nil {
			return err
		}

		return nil
	}
}


================================================
FILE: binding/json_content_type_binder.go
================================================
package binding

import (
	"encoding/json"
	"net/http"
)

// JSONContentTypeBinder is in charge of binding JSON request types.
type JSONContentTypeBinder struct{}

// BinderFunc returns the Binder for this JSONRequestTypeBinder
func (js JSONContentTypeBinder) BinderFunc() Binder {
	return func(req *http.Request, value any) error {
		return json.NewDecoder(req.Body).Decode(value)
	}
}

// ContentTypes that will be wired to this the JSON Binder
func (js JSONContentTypeBinder) ContentTypes() []string {
	return []string{
		"application/json",
		"text/json",
		"json",
	}
}


================================================
FILE: binding/request_binder.go
================================================
package binding

import (
	"errors"
	"fmt"
	"net/http"
	"strings"
	"sync"

	"github.com/gobuffalo/buffalo/internal/httpx"
)

var (
	errBlankContentType = errors.New("blank content type")
)

// RequestBinder is in charge of binding multiple requests types to
// struct.
type RequestBinder struct {
	lock    *sync.RWMutex
	binders map[string]Binder
}

// Register maps a request Content-Type (application/json)
// to a Binder.
func (rb *RequestBinder) Register(contentType string, fn Binder) {
	rb.lock.Lock()
	defer rb.lock.Unlock()

	rb.binders[strings.ToLower(contentType)] = fn
}

// Exec binds a request with a passed value, depending on the content type
// It will look for the correct RequestTypeBinder and use it.
func (rb *RequestBinder) Exec(req *http.Request, value any) error {
	rb.lock.Lock()
	defer rb.lock.Unlock()

	if ba, ok := value.(Bindable); ok {
		return ba.Bind(req)
	}

	ct := httpx.ContentType(req)
	if ct == "" {
		return errBlankContentType
	}

	binder := rb.binders[ct]
	if binder == nil {
		return fmt.Errorf("could not find a binder for %s", ct)
	}

	return binder(req, value)
}

// NewRequestBinder creates our request binder with support for
// XML, JSON, HTTP and File request types.
func NewRequestBinder(requestBinders ...ContenTypeBinder) *RequestBinder {
	result := &RequestBinder{
		lock:    &sync.RWMutex{},
		binders: map[string]Binder{},
	}

	for _, requestBinder := range requestBinders {
		for _, contentType := range requestBinder.ContentTypes() {
			result.Register(contentType, requestBinder.BinderFunc())
		}
	}

	return result
}


================================================
FILE: binding/request_binder_test.go
================================================
package binding

import (
	"errors"
	"net/http"
	"strings"
	"testing"

	"github.com/stretchr/testify/require"
)

func Test_RequestBinder_Exec(t *testing.T) {
	r := require.New(t)

	var used bool
	BaseRequestBinder.Register("paganotoni/test", func(*http.Request, any) error {
		used = true
		return nil
	})

	req, err := http.NewRequest("GET", "/home", strings.NewReader(""))
	req.Header.Add("content-type", "paganotoni/test")
	r.NoError(err)

	data := &struct{}{}
	r.NoError(BaseRequestBinder.Exec(req, data))
	r.True(used)
}

func Test_RequestBinder_Exec_BlankContentType(t *testing.T) {
	r := require.New(t)

	req, err := http.NewRequest("GET", "/home", strings.NewReader(""))
	r.NoError(err)

	data := &struct{}{}
	r.Equal(BaseRequestBinder.Exec(req, data), errBlankContentType)
}

func Test_RequestBinder_Exec_Bindable(t *testing.T) {
	r := require.New(t)

	BaseRequestBinder.Register("paganotoni/orbison", func(req *http.Request, val any) error {
		switch v := val.(type) {
		case orbison:
			v.bound = false
		}

		return errors.New("this should not be called")
	})

	req, err := http.NewRequest("GET", "/home", strings.NewReader(""))
	req.Header.Add("content-type", "paganotoni/orbison")
	r.NoError(err)

	data := &orbison{}
	r.NoError(BaseRequestBinder.Exec(req, data))
	r.True(data.bound)
}

func Test_RequestBinder_Exec_NoBinder(t *testing.T) {
	r := require.New(t)

	req, err := http.NewRequest("GET", "/home", strings.NewReader(""))
	req.Header.Add("content-type", "paganotoni/other")
	r.NoError(err)

	err = BaseRequestBinder.Exec(req, &struct{}{})
	r.Error(err)
	r.Equal(err.Error(), "could not find a binder for paganotoni/other")
}


================================================
FILE: binding/types.go
================================================
package binding

import (
	"net/http"
)

// ContenTypeBinder are those capable of handling a request type like JSON or XML
type ContenTypeBinder interface {
	BinderFunc() Binder
	ContentTypes() []string
}

// Binder takes a request and binds it to an interface.
// If there is a problem it should return an error.
type Binder func(*http.Request, any) error

// CustomTypeDecoder converts a custom type from the request into its exact type.
type CustomTypeDecoder func([]string) (any, error)


================================================
FILE: binding/xml_request_type_binder.go
================================================
package binding

import (
	"encoding/xml"
	"net/http"
)

// XMLRequestTypeBinder is in charge of binding XML request types.
type XMLRequestTypeBinder struct{}

// BinderFunc returns the Binder for this RequestTypeBinder
func (xm XMLRequestTypeBinder) BinderFunc() Binder {
	return func(req *http.Request, value any) error {
		return xml.NewDecoder(req.Body).Decode(value)
	}
}

// ContentTypes that will be wired to this the XML Binder
func (xm XMLRequestTypeBinder) ContentTypes() []string {
	return []string{
		"application/xml",
		"text/xml",
		"xml",
	}
}


================================================
FILE: buffalo.go
================================================
/*
Package buffalo is a Go web development eco-system, designed to make your life easier.

Buffalo helps you to generate a web project that already has everything from front-end (JavaScript, SCSS, etc.) to back-end (database, routing, etc.) already hooked up and ready to run. From there it provides easy APIs to build your web application quickly in Go.

Buffalo **isn't just a framework**, it's a holistic web development environment and project structure that **lets developers get straight to the business** of, well, building their business.
*/
package buffalo


================================================
FILE: context.go
================================================
package buffalo

import (
	"context"
	"net/http"
	"net/url"

	"github.com/gobuffalo/buffalo/binding"
	"github.com/gobuffalo/buffalo/internal/httpx"
	"github.com/gobuffalo/buffalo/render"
	"github.com/gorilla/mux"
)

// Context holds on to information as you
// pass it down through middleware, Handlers,
// templates, etc... It strives to make your
// life a happier one.
type Context interface {
	context.Context
	Response() http.ResponseWriter
	Request() *http.Request
	Session() *Session
	Cookies() *Cookies
	Params() ParamValues
	Param(string) string
	Set(string, any)
	LogField(string, any)
	LogFields(map[string]any)
	Logger() Logger
	Bind(any) error
	Render(int, render.Renderer) error
	Error(int, error) error
	Redirect(int, string, ...any) error
	Data() map[string]any
	Flash() *Flash
	File(string) (binding.File, error)
}

// ParamValues will most commonly be url.Values,
// but isn't it great that you set your own? :)
type ParamValues interface {
	Get(string) string
}

func (a *App) newContext(info RouteInfo, res http.ResponseWriter, req *http.Request) Context {
	if ws, ok := res.(*Response); ok {
		res = ws
	}

	// Parse URL Params
	params := url.Values{}
	vars := mux.Vars(req)
	for k, v := range vars {
		params.Add(k, v)
	}

	// Parse URL Query String Params
	// For POST, PUT, and PATCH requests, it also parse the request body as a form.
	// Request body parameters take precedence over URL query string values in params
	if err := req.ParseForm(); err == nil {
		for k, v := range req.Form {
			for _, vv := range v {
				params.Add(k, vv)
			}
		}
	}

	session := a.getSession(req, res)

	ct := httpx.ContentType(req)

	data := newRequestData()
	data.d = map[string]any{
		"app":           a,
		"env":           a.Env,
		"routes":        a.Routes(),
		"current_route": info,
		"current_path":  req.URL.Path,
		"contentType":   ct,
		"method":        req.Method,
	}

	for _, route := range a.Routes() {
		cRoute := route
		data.d[cRoute.PathName] = cRoute.BuildPathHelper()
	}

	return &DefaultContext{
		Context:     req.Context(),
		contentType: ct,
		response:    res,
		request:     req,
		params:      params,
		logger:      a.Logger,
		session:     session,
		flash:       newFlash(session),
		data:        data,
	}
}


================================================
FILE: cookies.go
================================================
package buffalo

import (
	"net/http"
	"time"
)

// Cookies allows you to easily get cookies from the request, and set cookies on the response.
type Cookies struct {
	req *http.Request
	res http.ResponseWriter
}

// Get returns the value of the cookie with the given name. Returns http.ErrNoCookie if there's no cookie with that name in the request.
func (c *Cookies) Get(name string) (string, error) {
	ck, err := c.req.Cookie(name)
	if err != nil {
		return "", err
	}

	return ck.Value, nil
}

// Set a cookie on the response, which will expire after the given duration.
func (c *Cookies) Set(name, value string, maxAge time.Duration) {
	ck := http.Cookie{
		Name:   name,
		Value:  value,
		MaxAge: int(maxAge.Seconds()),
	}

	http.SetCookie(c.res, &ck)
}

// SetWithExpirationTime sets a cookie that will expire at a specific time.
// Note that the time is determined by the client's browser, so it might not expire at the expected time,
// for example if the client has changed the time on their computer.
func (c *Cookies) SetWithExpirationTime(name, value string, expires time.Time) {
	ck := http.Cookie{
		Name:    name,
		Value:   value,
		Expires: expires,
	}

	http.SetCookie(c.res, &ck)
}

// SetWithPath sets a cookie path on the server in which the cookie will be available on.
// If set to '/', the cookie will be available within the entire domain.
// If set to '/foo/', the cookie will only be available within the /foo/ directory and
// all sub-directories such as /foo/bar/ of domain.
func (c *Cookies) SetWithPath(name, value, path string) {
	ck := http.Cookie{
		Name:  name,
		Value: value,
		Path:  path,
	}

	http.SetCookie(c.res, &ck)
}

// Delete sets a header that tells the browser to remove the cookie with the given name.
func (c *Cookies) Delete(name string) {
	ck := http.Cookie{
		Name:  name,
		Value: "v",
		// Setting a time in the distant past, like the unix epoch, removes the cookie,
		// since it has long expired.
		Expires: time.Unix(0, 0),
	}

	http.SetCookie(c.res, &ck)
}


================================================
FILE: cookies_test.go
================================================
package buffalo

import (
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func TestCookies_Get(t *testing.T) {
	r := require.New(t)
	req := httptest.NewRequest("POST", "/", nil)
	req.Header.Set("Cookie", "name=Arthur Dent; answer=42")

	c := Cookies{req, nil}

	v, err := c.Get("name")
	r.NoError(err)
	r.Equal("Arthur Dent", v)

	v, err = c.Get("answer")
	r.NoError(err)
	r.Equal("42", v)

	_, err = c.Get("unknown")
	r.EqualError(err, http.ErrNoCookie.Error())
}

func TestCookies_Set(t *testing.T) {
	r := require.New(t)
	res := httptest.NewRecorder()

	c := Cookies{&http.Request{}, res}

	c.Set("name", "Rob Pike", time.Hour*24)

	h := res.Header().Get("Set-Cookie")
	r.Equal("name=\"Rob Pike\"; Max-Age=86400", h)
}

func TestCookies_SetWithPath(t *testing.T) {
	r := require.New(t)
	res := httptest.NewRecorder()

	c := Cookies{&http.Request{}, res}

	c.SetWithPath("name", "Rob Pike", "/foo")

	h := res.Header().Get("Set-Cookie")
	r.Equal("name=\"Rob Pike\"; Path=/foo", h)
}

func TestCookies_SetWithExpirationTime(t *testing.T) {
	r := require.New(t)
	res := httptest.NewRecorder()

	c := Cookies{&http.Request{}, res}

	e := time.Date(2017, 7, 29, 19, 28, 45, 0, time.UTC)
	c.SetWithExpirationTime("name", "Rob Pike", e)

	h := res.Header().Get("Set-Cookie")
	r.Equal("name=\"Rob Pike\"; Expires=Sat, 29 Jul 2017 19:28:45 GMT", h)
}

func TestCookies_Delete(t *testing.T) {
	r := require.New(t)
	res := httptest.NewRecorder()

	c := Cookies{&http.Request{}, res}

	c.Delete("remove-me")

	h := res.Header().Get("Set-Cookie")
	r.Equal("remove-me=v; Expires=Thu, 01 Jan 1970 00:00:00 GMT", h)
}


================================================
FILE: default_context.go
================================================
package buffalo

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"maps"
	"net/http"
	"net/url"
	"reflect"
	"slices"
	"strings"
	"time"

	"github.com/gobuffalo/buffalo/binding"
	"github.com/gobuffalo/buffalo/render"
)

// assert that DefaultContext is implementing Context
var _ Context = &DefaultContext{}
var _ context.Context = &DefaultContext{}

// TODO(sio4): #road-to-v1 - make DefaultContext private
// and only allow it to be generated by App.newContext() or any similar.

// DefaultContext is, as its name implies, a default
// implementation of the Context interface.
type DefaultContext struct {
	context.Context
	response    http.ResponseWriter
	request     *http.Request
	params      url.Values
	logger      Logger
	session     *Session
	contentType string
	data        *requestData
	flash       *Flash
}

// Response returns the original Response for the request.
func (d *DefaultContext) Response() http.ResponseWriter {
	return d.response
}

// Request returns the original Request.
func (d *DefaultContext) Request() *http.Request {
	return d.request
}

// Params returns all of the parameters for the request,
// including both named params and query string parameters.
func (d *DefaultContext) Params() ParamValues {
	return d.params
}

// Logger returns the Logger for this context.
func (d *DefaultContext) Logger() Logger {
	return d.logger
}

// Param returns a param, either named or query string,
// based on the key.
func (d *DefaultContext) Param(key string) string {
	return d.Params().Get(key)
}

// Set a value onto the Context. Any value set onto the Context
// will be automatically available in templates.
func (d *DefaultContext) Set(key string, value any) {
	if d.data == nil {
		d.data = newRequestData()
	}
	d.data.moot.Lock()
	defer d.data.moot.Unlock()
	d.data.d[key] = value
}

// Value that has previously stored on the context.
func (d *DefaultContext) Value(key any) any {
	if k, ok := key.(string); ok && d.data != nil {
		d.data.moot.RLock()
		defer d.data.moot.RUnlock()
		if v, ok := d.data.d[k]; ok {

			return v
		}
	}
	if d.Context == nil {
		return nil
	}
	return d.Context.Value(key)
}

// Session for the associated Request.
func (d *DefaultContext) Session() *Session {
	return d.session
}

// Cookies for the associated request and response.
func (d *DefaultContext) Cookies() *Cookies {
	return &Cookies{d.request, d.response}
}

// Flash messages for the associated Request.
func (d *DefaultContext) Flash() *Flash {
	return d.flash
}

type paginable interface {
	Paginate() string
}

// Render a status code and render.Renderer to the associated Response.
// The request parameters will be made available to the render.Renderer
// "{{.params}}". Any values set onto the Context will also automatically
// be made available to the render.Renderer. To render "no content" pass
// in a nil render.Renderer.
func (d *DefaultContext) Render(status int, rr render.Renderer) error {
	start := time.Now()
	defer func() {
		d.LogField("render", time.Since(start))
	}()

	if rr == nil {
		d.Response().WriteHeader(status)
		return nil
	}

	data := d.Data()
	pp := map[string]string{}
	for k, v := range d.params {
		pp[k] = v[0]
	}
	data["params"] = pp
	data["flash"] = d.Flash().data
	data["session"] = d.Session()
	data["request"] = d.Request()
	data["status"] = status
	bb := &bytes.Buffer{}

	err := rr.Render(bb, data)
	if err != nil {
		var er render.ErrRedirect
		if errors.As(err, &er) {
			return d.Redirect(er.Status, er.URL)
		}
		return HTTPError{Status: http.StatusInternalServerError, Cause: err}
	}

	if d.Session() != nil {
		d.Flash().Clear()
		d.Flash().persist(d.Session())
		if err := d.Session().Save(); err != nil {
			return HTTPError{Status: http.StatusInternalServerError, Cause: err}
		}
	}

	d.Response().Header().Set("Content-Type", rr.ContentType())
	if p, ok := data["pagination"].(paginable); ok {
		d.Response().Header().Set("X-Pagination", p.Paginate())
	}
	d.Response().WriteHeader(status)
	_, err = io.Copy(d.Response(), bb)
	if err != nil {
		return HTTPError{Status: http.StatusInternalServerError, Cause: err}
	}

	return nil
}

// Bind the interface to the request.Body. The type of binding
// is dependent on the "Content-Type" for the request. If the type
// is "application/json" it will use "json.NewDecoder". If the type
// is "application/xml" it will use "xml.NewDecoder". See the
// github.com/gobuffalo/buffalo/binding package for more details.
func (d *DefaultContext) Bind(value any) error {
	return binding.Exec(d.Request(), value)
}

// LogField adds the key/value pair onto the Logger to be printed out
// as part of the request logging. This allows you to easily add things
// like metrics (think DB times) to your request.
func (d *DefaultContext) LogField(key string, value any) {
	if d.logger == nil {
		return
	}
	d.logger = d.logger.WithField(key, value)
}

// LogFields adds the key/value pairs onto the Logger to be printed out
// as part of the request logging. This allows you to easily add things
// like metrics (think DB times) to your request.
func (d *DefaultContext) LogFields(values map[string]any) {
	if d.logger == nil {
		return
	}
	d.logger = d.logger.WithFields(values)
}

func (d *DefaultContext) Error(status int, err error) error {
	return HTTPError{Status: status, Cause: err}
}

var mapType = reflect.ValueOf(map[string]any{}).Type()

// Redirect a request with the given status to the given URL.
func (d *DefaultContext) Redirect(status int, url string, args ...any) error {
	if d.Session() != nil {
		d.Flash().persist(d.Session())
		if err := d.Session().Save(); err != nil {
			return HTTPError{Status: http.StatusInternalServerError, Cause: err}
		}
	}

	if strings.HasSuffix(url, "Path()") {
		if len(args) > 1 {
			return fmt.Errorf("you must pass only a map[string]any to a route path: %T", args)
		}
		var m map[string]any
		if len(args) == 1 {
			rv := reflect.Indirect(reflect.ValueOf(args[0]))
			if !rv.Type().ConvertibleTo(mapType) {
				return fmt.Errorf("you must pass only a map[string]any to a route path: %T", args)
			}
			m = rv.Convert(mapType).Interface().(map[string]any)
		}
		h, ok := d.Value(strings.TrimSuffix(url, "()")).(RouteHelperFunc)
		if !ok {
			return fmt.Errorf("could not find a route helper named %s", url)
		}
		url, err := h(m)
		if err != nil {
			return err
		}
		http.Redirect(d.Response(), d.Request(), string(url), status)
		return nil
	}

	if len(args) > 0 {
		url = fmt.Sprintf(url, args...)
	}
	http.Redirect(d.Response(), d.Request(), url, status)
	return nil
}

// Data contains all the values set through Get/Set.
func (d *DefaultContext) Data() map[string]any {
	m := map[string]any{}

	if d.data == nil {
		return m
	}
	d.data.moot.RLock()
	defer d.data.moot.RUnlock()
	m = maps.Clone(d.data.d)
	return m
}

func (d *DefaultContext) String() string {
	data := d.Data()
	bb := make([]string, 0, len(data))

	for k, v := range data {
		if _, ok := v.(RouteHelperFunc); !ok {
			bb = append(bb, fmt.Sprintf("%s: %s", k, v))
		}
	}
	slices.Sort(bb)
	return strings.Join(bb, "\n\n")
}

// File returns an uploaded file by name, or an error
func (d *DefaultContext) File(name string) (binding.File, error) {
	req := d.Request()
	if err := req.ParseMultipartForm(5 * 1024 * 1024); err != nil {
		return binding.File{}, err
	}
	f, h, err := req.FormFile(name)
	bf := binding.File{
		File:       f,
		FileHeader: h,
	}
	return bf, err
}

// MarshalJSON implements json marshaling for the context
func (d *DefaultContext) MarshalJSON() ([]byte, error) {
	m := map[string]any{}
	data := d.Data()
	for k, v := range data {
		// don't try and marshal ourself
		if _, ok := v.(*DefaultContext); ok {
			continue
		}
		if _, err := json.Marshal(v); err == nil {
			// it can be marshaled, so add it:
			m[k] = v
		}
	}
	return json.Marshal(m)
}


================================================
FILE: default_context_test.go
================================================
package buffalo

import (
	"bytes"
	"context"
	"net/http"
	"net/url"
	"testing"

	"github.com/gobuffalo/buffalo/render"
	"github.com/gobuffalo/httptest"
	"github.com/gobuffalo/logger"
	"github.com/stretchr/testify/require"
)

func basicContext() DefaultContext {
	return DefaultContext{
		Context: context.Background(),
		logger:  logger.New(logger.DebugLevel),
		data:    newRequestData(),
		flash:   &Flash{data: make(map[string][]string)},
	}
}

func Test_DefaultContext_Redirect(t *testing.T) {
	r := require.New(t)
	a := New(Options{})
	u := "/foo?bar=http%3A%2F%2Flocalhost%3A3000%2Flogin%2Fcallback%2Ffacebook"
	a.GET("/", func(c Context) error {
		return c.Redirect(http.StatusFound, u)
	})

	w := httptest.New(a)
	res := w.HTML("/").Get()
	r.Equal(u, res.Location())
}

func Test_DefaultContext_Redirect_Helper(t *testing.T) {
	r := require.New(t)

	table := []struct {
		E string
		I map[string]any
		S int
	}{
		{
			E: "/foo/baz/",
			I: map[string]any{"bar": "baz"},
			S: http.StatusPermanentRedirect,
		},
		{
			S: http.StatusInternalServerError,
		},
	}

	for _, tt := range table {
		a := New(Options{})
		a.GET("/foo/{bar}", func(c Context) error {
			return c.Render(http.StatusOK, render.String(c.Param("bar")))
		})
		a.GET("/", func(c Context) error {
			return c.Redirect(http.StatusPermanentRedirect, "fooBarPath()", tt.I)
		})
		a.GET("/nomap", func(c Context) error {
			return c.Redirect(http.StatusPermanentRedirect, "rootPath()")
		})

		w := httptest.New(a)
		res := w.HTML("/").Get()
		r.Equal(tt.S, res.Code)
		r.Equal(tt.E, res.Location())

		res = w.HTML("/nomap").Get()
		r.Equal(http.StatusPermanentRedirect, res.Code)
		r.Equal("/", res.Location())
	}
}

func Test_DefaultContext_Param(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{
		params: url.Values{
			"name": []string{"Mark"},
		},
	}

	r.Equal("Mark", c.Param("name"))
}

func Test_DefaultContext_Param_form(t *testing.T) {
	r := require.New(t)

	app := New(Options{})
	var name string
	app.POST("/", func(c Context) error {
		name = c.Param("name")
		return nil
	})

	w := httptest.New(app)
	res := w.HTML("/").Post(map[string]string{
		"name": "Mark",
	})

	r.Equal(http.StatusOK, res.Code)
	r.Equal("Mark", name)
}

func Test_DefaultContext_Param_Multiple(t *testing.T) {
	r := require.New(t)

	app := New(Options{})
	var params ParamValues
	var param string
	app.POST("/{id}", func(c Context) error {
		params = c.Params()
		param = c.Param("id")
		return nil
	})

	w := httptest.New(app)
	res := w.HTML("/a?id=c&y=z&id=d").Post(map[string]string{
		"id": "b",
	})
	paramsExpected := url.Values{
		"id": []string{"a", "b", "c", "d"},
		"y":  []string{"z"},
	}

	r.Equal(200, res.Code)
	r.Equal(paramsExpected, params.(url.Values))
	r.Equal("a", param)
}

func Test_DefaultContext_GetSet(t *testing.T) {
	r := require.New(t)
	c := basicContext()
	r.Nil(c.Value("name"))

	c.Set("name", "Mark")
	r.NotNil(c.Value("name"))
	r.Equal("Mark", c.Value("name").(string))
}

func Test_DefaultContext_Set_not_configured(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{}

	c.Set("name", "Yonghwan")
	r.NotNil(c.Value("name"))
	r.Equal("Yonghwan", c.Value("name").(string))
}

func Test_DefaultContext_Value(t *testing.T) {
	r := require.New(t)
	c := basicContext()
	r.Nil(c.Value("name"))

	c.Set("name", "Mark")
	r.NotNil(c.Value("name"))
	r.Equal("Mark", c.Value("name").(string))
}

func Test_DefaultContext_Value_not_configured(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{}
	r.Nil(c.Value("name"))
}

func Test_DefaultContext_Render(t *testing.T) {
	r := require.New(t)

	c := basicContext()
	res := httptest.NewRecorder()
	c.response = res
	c.params = url.Values{"name": []string{"Mark"}}
	c.Set("greet", "Hello")

	err := c.Render(http.StatusTeapot, render.String(`<%= greet %> <%= params["name"] %>!`))
	r.NoError(err)

	r.Equal(http.StatusTeapot, res.Code)
	r.Equal("Hello Mark!", res.Body.String())
}

func Test_DefaultContext_Bind_Default(t *testing.T) {
	r := require.New(t)

	user := struct {
		FirstName string `form:"first_name"`
	}{}

	a := New(Options{})
	a.POST("/", func(c Context) error {
		err := c.Bind(&user)
		if err != nil {
			return err
		}
		return c.Render(http.StatusCreated, nil)
	})

	w := httptest.New(a)
	uv := url.Values{"first_name": []string{"Mark"}}
	res := w.HTML("/").Post(uv)
	r.Equal(http.StatusCreated, res.Code)

	r.Equal("Mark", user.FirstName)
}

func Test_DefaultContext_Bind_No_ContentType(t *testing.T) {
	r := require.New(t)

	user := struct {
		FirstName string `form:"first_name"`
	}{
		FirstName: "Mark",
	}

	a := New(Options{})
	a.POST("/", func(c Context) error {
		err := c.Bind(&user)
		if err != nil {
			return c.Error(http.StatusUnprocessableEntity, err)
		}
		return c.Render(http.StatusCreated, nil)
	})

	bb := &bytes.Buffer{}
	req, err := http.NewRequest("POST", "/", bb)
	r.NoError(err)
	req.Header.Del("Content-Type")
	res := httptest.NewRecorder()
	a.ServeHTTP(res, req)
	r.Equal(http.StatusUnprocessableEntity, res.Code)
	r.Contains(res.Body.String(), "blank content type")
}

func Test_DefaultContext_Bind_Empty_ContentType(t *testing.T) {
	r := require.New(t)

	user := struct {
		FirstName string `form:"first_name"`
	}{
		FirstName: "Mark",
	}

	a := New(Options{})
	a.POST("/", func(c Context) error {
		err := c.Bind(&user)
		if err != nil {
			return c.Error(http.StatusUnprocessableEntity, err)
		}
		return c.Render(http.StatusCreated, nil)
	})

	bb := &bytes.Buffer{}
	req, err := http.NewRequest("POST", "/", bb)
	r.NoError(err)
	// Want to make sure that an empty string value does not cause an error on `split`
	req.Header.Set("Content-Type", "")
	res := httptest.NewRecorder()
	a.ServeHTTP(res, req)
	r.Equal(http.StatusUnprocessableEntity, res.Code)
	r.Contains(res.Body.String(), "blank content type")
}

func Test_DefaultContext_Bind_Default_BlankFields(t *testing.T) {
	r := require.New(t)

	user := struct {
		FirstName string `form:"first_name"`
	}{
		FirstName: "Mark",
	}

	a := New(Options{})
	a.POST("/", func(c Context) error {
		err := c.Bind(&user)
		if err != nil {
			return err
		}
		return c.Render(http.StatusCreated, nil)
	})

	w := httptest.New(a)
	uv := url.Values{"first_name": []string{""}}
	res := w.HTML("/").Post(uv)
	r.Equal(http.StatusCreated, res.Code)

	r.Equal("", user.FirstName)
}

func Test_DefaultContext_Bind_JSON(t *testing.T) {
	r := require.New(t)

	user := struct {
		FirstName string `json:"first_name"`
	}{}

	a := New(Options{})
	a.POST("/", func(c Context) error {
		err := c.Bind(&user)
		if err != nil {
			return err
		}
		return c.Render(http.StatusCreated, nil)
	})

	w := httptest.New(a)
	res := w.JSON("/").Post(map[string]string{
		"first_name": "Mark",
	})
	r.Equal(http.StatusCreated, res.Code)

	r.Equal("Mark", user.FirstName)
}

func Test_DefaultContext_Data(t *testing.T) {
	r := require.New(t)
	c := basicContext()

	r.EqualValues(map[string]any{}, c.Data())
}

func Test_DefaultContext_Data_not_configured(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{}

	r.EqualValues(map[string]any{}, c.Data())
}

func Test_DefaultContext_String(t *testing.T) {
	r := require.New(t)
	c := basicContext()
	c.Set("name", "Buffalo")
	c.Set("language", "go")

	r.EqualValues("language: go\n\nname: Buffalo", c.String())
}

func Test_DefaultContext_String_EmptyData(t *testing.T) {
	r := require.New(t)
	c := basicContext()
	r.EqualValues("", c.String())
}

func Test_DefaultContext_String_EmptyData_not_configured(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{}

	r.EqualValues("", c.String())
}

func Test_DefaultContext_MarshalJSON(t *testing.T) {
	r := require.New(t)
	c := basicContext()
	c.Set("name", "Buffalo")
	c.Set("language", "go")

	jb, err := c.MarshalJSON()
	r.NoError(err)
	r.EqualValues(`{"language":"go","name":"Buffalo"}`, string(jb))
}

func Test_DefaultContext_MarshalJSON_EmptyData(t *testing.T) {
	r := require.New(t)
	c := basicContext()

	jb, err := c.MarshalJSON()
	r.NoError(err)
	r.EqualValues(`{}`, string(jb))
}

func Test_DefaultContext_MarshalJSON_EmptyData_not_configured(t *testing.T) {
	r := require.New(t)
	c := DefaultContext{}

	jb, err := c.MarshalJSON()
	r.NoError(err)
	r.EqualValues(`{}`, string(jb))
}


================================================
FILE: errors.go
================================================
package buffalo

import (
	"database/sql"
	_ "embed"
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"net/http"
	"runtime/debug"
	"slices"
	"strings"

	"github.com/gobuffalo/buffalo/internal/defaults"
	"github.com/gobuffalo/buffalo/internal/httpx"
	"github.com/gobuffalo/events"
	"github.com/gobuffalo/plush/v5"
)

var (
	//go:embed internal/templates/error.dev.html
	devErrorTmpl string

	//go:embed internal/templates/error.prod.html
	prodErrorTmpl string

	//go:embed internal/templates/notfound.prod.html
	prodNotFoundTmpl string
)

// HTTPError a typed error returned by http Handlers and used for choosing error handlers
type HTTPError struct {
	Status int   `json:"status"`
	Cause  error `json:"error"`
}

// Unwrap allows the error to be unwrapped.
func (h HTTPError) Unwrap() error {
	return h.Cause
}

// Error returns the cause of the error as string.
func (h HTTPError) Error() string {
	if h.Cause != nil {
		return h.Cause.Error()
	}
	return "unknown cause"
}

// ErrorHandler interface for handling an error for a
// specific status code.
type ErrorHandler func(int, error, Context) error

// ErrorHandlers is used to hold a list of ErrorHandler
// types that can be used to handle specific status codes.
/*
	a.ErrorHandlers[http.StatusInternalServerError] = func(status int, err error, c buffalo.Context) error {
		res := c.Response()
		res.WriteHeader(status)
		res.Write([]byte(err.Error()))
		return nil
	}
*/
type ErrorHandlers map[int]ErrorHandler

// Get a registered ErrorHandler for this status code. If
// no ErrorHandler has been registered, a default one will
// be returned.
func (e ErrorHandlers) Get(status int) ErrorHandler {
	if eh, ok := e[status]; ok {
		return eh
	}
	if eh, ok := e[0]; ok {
		return eh
	}
	return defaultErrorHandler
}

// Default sets an error handler should a status
// code not already be mapped. This will replace
// the original default error handler.
// This is a *catch-all* handler.
func (e ErrorHandlers) Default(eh ErrorHandler) {
	if eh != nil {
		e[0] = eh
	}
}

// PanicHandler recovers from panics gracefully and calls
// the error handling code for a 500 error.
func (a *App) PanicHandler(next Handler) Handler {
	return func(c Context) error {
		defer func() { //catch or finally
			r := recover()
			var err error
			if r != nil { //catch
				switch t := r.(type) {
				case error:
					err = t
				case string:
					err = fmt.Errorf("%s", t)
				default:
					err = fmt.Errorf("%s", fmt.Sprint(t))
				}

				payload := events.Payload{
					"context":    c,
					"app":        a,
					"stacktrace": string(debug.Stack()),
					"error":      err,
				}
				events.EmitError(events.ErrPanic, err, payload)

				eh := a.ErrorHandlers.Get(http.StatusInternalServerError)
				eh(http.StatusInternalServerError, err, c)
			}
		}()
		return next(c)
	}
}

func (a *App) defaultErrorMiddleware(next Handler) Handler {
	return func(c Context) error {
		err := next(c)
		if err == nil {
			return nil
		}

		// 500 Internal Server Error by default
		status := http.StatusInternalServerError

		// unpack root err and check for HTTPError
		if errors.Is(err, sql.ErrNoRows) {
			status = http.StatusNotFound
		}
		var h HTTPError
		if errors.As(err, &h) {
			status = h.Status
		}

		payload := events.Payload{
			"context": c,
			"app":     a,
			"status":  status,
			"error":   err,
		}
		if status >= http.StatusInternalServerError {
			// we need the details (or stack trace) only for 5xx errors.
			// pkg/errors supports '%+v' for stack trace.
			// the other type of errors that support '%+v' is also supported.
			payload["stacktrace"] = fmt.Sprintf("%+v", err)
		}
		events.EmitError(events.ErrGeneral, err, payload)

		eh := a.ErrorHandlers.Get(status)
		err = eh(status, err, c)
		if err != nil {
			events.Emit(events.Event{
				Kind:    EvtFailureErr,
				Message: "unable to handle error and giving up",
				Error:   err,
				Payload: payload,
			})
			// things have really hit the fan if we're here!!
			a.Logger.Error(err)
			c.Response().WriteHeader(http.StatusInternalServerError)
			c.Response().Write([]byte(err.Error()))
		}
		return nil
	}
}

func productionErrorResponseFor(status int) []byte {
	if status == http.StatusNotFound {
		return []byte(prodNotFoundTmpl)
	}

	return []byte(prodErrorTmpl)
}

// ErrorResponse is a used to display errors as JSON or XML
type ErrorResponse struct {
	XMLName xml.Name `json:"-" xml:"response"`
	Error   string   `json:"error" xml:"error"`
	Trace   string   `json:"trace,omitempty" xml:"trace,omitempty"`
	Code    int      `json:"code" xml:"code,attr"`
}

const defaultErrorCT = "text/html; charset=utf-8"

func defaultErrorHandler(status int, origErr error, c Context) error {
	env := c.Value("env")
	requestCT := defaults.String(httpx.ContentType(c.Request()), defaultErrorCT)

	var defaultErrorResponse *ErrorResponse

	c.LogField("status", status)
	c.Logger().Error(origErr)
	c.Response().WriteHeader(status)

	if env != nil && env.(string) != "development" {
		switch strings.ToLower(requestCT) {
		case "application/json", "text/json", "json", "application/xml", "text/xml", "xml":
			defaultErrorResponse = &ErrorResponse{
				Code:  status,
				Error: http.StatusText(status),
			}
		default:
			c.Response().Header().Set("content-type", defaultErrorCT)
			responseBody := productionErrorResponseFor(status)
			c.Response().Write(responseBody)
			return nil
		}
	}

	trace := fmt.Sprintf("%+v", origErr)
	if cause := errors.Unwrap(origErr); cause != nil {
		origErr = cause
	}

	errResponse := errorResponseDefault(defaultErrorResponse, &ErrorResponse{
		Error: origErr.Error(),
		Trace: trace,
		Code:  status,
	})

	switch strings.ToLower(requestCT) {
	case "application/json", "text/json", "json":
		c.Response().Header().Set("content-type", "application/json")
		err := json.NewEncoder(c.Response()).Encode(errResponse)
		if err != nil {
			return err
		}
	case "application/xml", "text/xml", "xml":
		c.Response().Header().Set("content-type", "text/xml")
		err := xml.NewEncoder(c.Response()).Encode(errResponse)
		if err != nil {
			return err
		}
	default:
		c.Response().Header().Set("content-type", defaultErrorCT)
		if err := c.Request().ParseForm(); err != nil {
			trace = fmt.Sprintf("%s\n%s", err.Error(), trace)
		}

		routes := c.Value("routes")
		cd := c.Data()

		delete(cd, "app")
		delete(cd, "routes")

		data := map[string]any{
			"routes":      routes,
			"error":       trace,
			"status":      status,
			"data":        cd,
			"params":      c.Params(),
			"posted_form": c.Request().Form,
			"context":     c,
			"headers":     inspectHeaders(c.Request().Header),
			"inspect": func(v any) string {
				return fmt.Sprintf("%+v", v)
			},
		}

		ctx := plush.NewContextWith(data)
		t, err := plush.Render(devErrorTmpl, ctx)
		if err != nil {
			return err
		}

		_, err = c.Response().Write([]byte(t))
		return err
	}
	return nil
}

func errorResponseDefault(defaultResponse, alternativeResponse *ErrorResponse) *ErrorResponse {
	if defaultResponse != nil {
		return defaultResponse
	}
	return alternativeResponse
}

type inspectHeaders http.Header

func (i inspectHeaders) String() string {

	bb := make([]string, 0, len(i))

	for k, v := range i {
		bb = append(bb, fmt.Sprintf("%s: %s", k, v))
	}
	slices.Sort(bb)
	return strings.Join(bb, "\n")
}


================================================
FILE: errors_test.go
================================================
package buffalo

import (
	"fmt"
	"net/http"
	"os"
	"testing"

	"github.com/gobuffalo/httptest"
	"github.com/gobuffalo/logger"
	"github.com/sirupsen/logrus"

	"github.com/stretchr/testify/require"
)

// testLoggerHook is useful to test whats being logged.
type testLoggerHook struct {
	errors []*logrus.Entry
}

func (lh *testLoggerHook) Fire(entry *logrus.Entry) error {
	lh.errors = append(lh.errors, entry)
	return nil
}

func (lh *testLoggerHook) Levels() []logrus.Level {
	return []logrus.Level{
		logrus.ErrorLevel,
	}
}

func Test_defaultErrorHandler_SetsContentType(t *testing.T) {
	r := require.New(t)
	app := New(Options{})
	app.GET("/", func(c Context) error {
		return c.Error(http.StatusUnauthorized, fmt.Errorf("boom"))
	})

	w := httptest.New(app)
	res := w.HTML("/").Get()
	r.Equal(http.StatusUnauthorized, res.Code)
	ct := res.Header().Get("content-type")
	r.Equal("text/html; charset=utf-8", ct)
}

func Test_defaultErrorHandler_Logger(t *testing.T) {
	r := require.New(t)
	app := New(Options{})
	app.GET("/", func(c Context) error {
		return c.Error(http.StatusUnauthorized, fmt.Errorf("boom"))
	})

	testHook := &testLoggerHook{}
	l := logrus.New()
	l.SetOutput(os.Stdout)
	l.AddHook(testHook)
	log := logger.Logrus{
		FieldLogger: l,
	}
	app.Logger = log

	w := httptest.New(app)
	res := w.HTML("/").Get()
	r.Equal(http.StatusUnauthorized, res.Code)
	r.Equal(http.StatusUnauthorized, testHook.errors[0].Data["status"])
}

func Test_defaultErrorHandler_JSON_development(t *testing.T) {
	testDefaultErrorHandler(t, "application/json", "development")
}

func Test_defaultErrorHandler_XML_development(t *testing.T) {
	testDefaultErrorHandler(t, "text/xml", "development")
}

func Test_defaultErrorHandler_JSON_staging(t *testing.T) {
	testDefaultErrorHandler(t, "application/json", "staging")
}

func Test_defaultErrorHandler_XML_staging(t *testing.T) {
	testDefaultErrorHandler(t, "text/xml", "staging")
}

func Test_defaultErrorHandler_JSON_production(t *testing.T) {
	testDefaultErrorHandler(t, "application/json", "production")
}

func Test_defaultErrorHandler_XML_production(t *testing.T) {
	testDefaultErrorHandler(t, "text/xml", "production")
}

func testDefaultErrorHandler(t *testing.T, contentType, env string) {
	r := require.New(t)
	app := New(Options{})
	app.Env = env
	app.GET("/", func(c Context) error {
		return c.Error(http.StatusUnauthorized, fmt.Errorf("boom"))
	})

	w := httptest.New(app)
	var res *httptest.Response
	if contentType == "application/json" {
		res = w.JSON("/").Get().Response
	} else {
		res = w.XML("/").Get().Response
	}
	r.Equal(http.StatusUnauthorized, res.Code)
	ct := res.Header().Get("content-type")
	r.Equal(contentType, ct)
	b := res.Body.String()

	if env == "development" {
		if contentType == "text/xml" {
			r.Contains(b, `<response code="401">`)
			r.Contains(b, `<error>boom</error>`)
			r.Contains(b, `<trace>`)
			r.Contains(b, `</trace>`)
			r.Contains(b, `</response>`)
		} else {
			r.Contains(b, `"code":401`)
			r.Contains(b, `"error":"boom"`)
			r.Contains(b, `"trace":"`)
		}
	} else {
		if contentType == "text/xml" {
			r.Contains(b, `<response code="401">`)
			r.Contains(b, fmt.Sprintf(`<error>%s</error>`, http.StatusText(http.StatusUnauthorized)))
			r.NotContains(b, `<trace>`)
			r.NotContains(b, `</trace>`)
			r.Contains(b, `</response>`)
		} else {
			r.Contains(b, `"code":401`)
			r.Contains(b, fmt.Sprintf(`"error":"%s"`, http.StatusText(http.StatusUnauthorized)))
			r.NotContains(b, `"trace":"`)
		}
	}
}

func Test_defaultErrorHandler_nil_error(t *testing.T) {
	r := require.New(t)
	app := New(Options{})
	app.GET("/", func(c Context) error {
		return c.Error(http.StatusInternalServerError, nil)
	})

	w := httptest.New(app)
	res := w.JSON("/").Get()
	r.Equal(http.StatusInternalServerError, res.Code)
}

func Test_PanicHandler(t *testing.T) {
	app := New(Options{})
	app.GET("/string", func(c Context) error {
		panic("string boom")
	})
	app.GET("/error", func(c Context) error {
		panic(fmt.Errorf("error boom"))
	})

	table := []struct {
		path     string
		expected string
	}{
		{"/string", "string boom"},
		{"/error", "error boom"},
	}

	const stack = `github.com/gobuffalo/buffalo.Test_PanicHandler`

	w := httptest.New(app)
	for _, tt := range table {
		t.Run(tt.path, func(st *testing.T) {
			r := require.New(st)

			res := w.HTML("%s", tt.path).Get()
			r.Equal(http.StatusInternalServerError, res.Code)

			body := res.Body.String()
			r.Contains(body, tt.expected)
			r.Contains(body, stack)
		})
	}
}

func Test_defaultErrorMiddleware(t *testing.T) {
	r := require.New(t)
	app := New(Options{})
	var x string
	var ok bool
	app.ErrorHandlers[http.StatusUnprocessableEntity] = func(code int, err error, c Context) error {
		x, ok = c.Value("T").(string)
		c.Response().WriteHeader(code)
		c.Response().Write([]byte(err.Error()))
		return nil
	}
	app.Use(func(next Handler) Handler {
		return func(c Context) error {
			c.Set("T", "t")
			return c.Error(http.StatusUnprocessableEntity, fmt.Errorf("boom"))
		}
	})
	app.GET("/", func(c Context) error {
		return nil
	})

	w := httptest.New(app)
	res := w.HTML("/").Get()
	r.Equal(http.StatusUnprocessableEntity, res.Code)
	r.True(ok)
	r.Equal("t", x)
}

func Test_SetErrorMiddleware(t *testing.T) {
	r := require.New(t)
	app := New(Options{})
	app.ErrorHandlers.Default(func(code int, err error, c Context) error {
		res := c.Response()
		res.WriteHeader(http.StatusTeapot)
		res.Write([]byte("i'm a teapot"))
		return nil
	})
	app.GET("/", func(c Context) error {
		return c.Error(http.StatusUnprocessableEntity, fmt.Errorf("boom"))
	})

	w := httptest.New(app)
	res := w.HTML("/").Get()
	r.Equal(http.StatusTeapot, res.Code)
	r.Equal("i'm a teapot", res.Body.String())
}


================================================
FILE: events.go
================================================
package buffalo

// TODO: TODO-v1 check if they are really need to be exported.
/* The event id should be unique across packages as the format of
   "<package-name>:<additional-names>:<optional-error>" as documented. They
   should not be used by another packages to keep it informational. To make
   it sure, they need to be internal.
   Especially for plugable conponents like servers or workers, they can have
   their own event definition if they need but the buffalo runtime can emit
   generalize events when e.g. the runtime calls configured worker.
*/
const (
	// EvtAppStart is emitted when buffalo.App#Serve is called
	EvtAppStart = "buffalo:app:start"
	// EvtAppStartErr is emitted when an error occurs calling buffalo.App#Serve
	EvtAppStartErr = "buffalo:app:start:err"

	// EvtAppStop is emitted when buffalo.App#Stop is called
	EvtAppStop = "buffalo:app:stop"
	// EvtAppStopErr is emitted when an error occurs calling buffalo.App#Stop
	EvtAppStopErr = "buffalo:app:stop:err"

	// EvtRouteStarted is emitted when a requested route is being processed
	EvtRouteStarted = "buffalo:route:started"
	// EvtRouteFinished is emitted when a requested route is completed
	EvtRouteFinished = "buffalo:route:finished"
	// EvtRouteErr is emitted when there is a problem handling processing a route
	EvtRouteErr = "buffalo:route:err"

	// EvtServerStart is emitted when buffalo is about to start servers
	EvtServerStart = "buffalo:server:start"
	// EvtServerStartErr is emitted when an error occurs when starting servers
	EvtServerStartErr = "buffalo:server:start:err"
	// EvtServerStop is emitted when buffalo is about to stop servers
	EvtServerStop = "buffalo:server:stop"
	// EvtServerStopErr is emitted when an error occurs when stopping servers
	EvtServerStopErr = "buffalo:server:stop:err"

	// EvtWorkerStart is emitted when buffalo is about to start workers
	EvtWorkerStart = "buffalo:worker:start"
	// EvtWorkerStartErr is emitted when an error occurs when starting workers
	EvtWorkerStartErr = "buffalo:worker:start:err"
	// EvtWorkerStop is emitted when buffalo is about to stop workers
	EvtWorkerStop = "buffalo:worker:stop"
	// EvtWorkerStopErr is emitted when an error occurs when stopping workers
	EvtWorkerStopErr = "buffalo:worker:stop:err"

	// EvtFailureErr is emitted when something can't be processed at all. it is a bad thing
	EvtFailureErr = "buffalo:failure:err"
)


================================================
FILE: flash.go
================================================
package buffalo

import "encoding/json"

// flashKey is the prefix inside the Session.
const flashKey = "_flash_"

// Flash is a struct that helps with the operations over flash messages.
type Flash struct {
	data map[string][]string
}

// Delete removes a particular key from the Flash.
func (f Flash) Delete(key string) {
	delete(f.data, key)
}

// Clear removes all keys from the Flash.
func (f *Flash) Clear() {
	f.data = map[string][]string{}
}

// Set allows to set a list of values into a particular key.
func (f Flash) Set(key string, values []string) {
	f.data[key] = values
}

// Add adds a flash value for a flash key, if the key already has values the list for that value grows.
func (f Flash) Add(key, value string) {
	if len(f.data[key]) == 0 {
		f.data[key] = []string{value}
		return
	}

	f.data[key] = append(f.data[key], value)
}

// Persist the flash inside the session.
func (f Flash) persist(session *Session) {
	b, _ := json.Marshal(f.data)
	session.Set(flashKey, b)
}

// newFlash creates a new Flash and loads the session data inside its data.
func newFlash(session *Session) *Flash {
	result := &Flash{
		data: map[string][]string{},
	}

	if session.Session != nil {
		if f := session.Get(flashKey); f != nil {
			json.Unmarshal(f.([]byte), &result.data)
		}
	}
	return result
}


================================================
FILE: flash_test.go
================================================
package buffalo

import (
	"net/http"
	"testing"
	"text/template"

	"github.com/gobuffalo/buffalo/render"
	"github.com/gobuffalo/httptest"
	"github.com/stretchr/testify/require"
)

func Test_FlashAdd(t *testing.T) {
	r := require.New(t)
	f := newFlash(&Session{})

	r.Equal(f.data, map[string][]string{})

	f.Add("error", "something")
	r.Equal(f.data, map[string][]string{
		"error": {"something"},
	})

	f.Add("error", "other")
	r.Equal(f.data, map[string][]string{
		"error": {"something", "other"},
	})
}

func Test_FlashRender(t *testing.T) {
	r := require.New(t)
	a := New(Options{})
	rr := render.New(render.Options{})

	a.GET("/", func(c Context) error {
		c.Flash().Add("errors", "Error AJ set")
		c.Flash().Add("errors", "Error DAL set")

		return c.Render(http.StatusCreated, rr.String(errorsTPL))
	})

	w := httptest.New(a)
	res := w.HTML("/").Get()

	r.Contains(res.Body.String(), "Error AJ set")
	r.Contains(res.Body.String(), "Error DAL set")
}

func Test_FlashRenderEmpty(t *testing.T) {
	r := require.New(t)
	a := New(Options{})
	rr := render.New(render.Options{})

	a.GET("/", func(c Context) error {
		return c.Render(http.StatusCreated, rr.String(errorsTPL))
	})

	w := httptest.New(a)

	res := w.HTML("/").Get()
	r.NotContains(res.Body.String(), "Flash:")
}

const errorsTPL = `
<%= for (k, v) in flash["errors"] { %>
	Flash:
		<%= k %>:<%= v %>
<% } %>
`

func Test_FlashRenderEntireFlash(t *testing.T) {
	r := require.New(t)
	a := New(Options{})
	rr := render.New(render.Options{})

	a.GET("/", func(c Context) error {
		c.Flash().Add("something", "something to say!")
		return c.Render(http.StatusCreated, rr.String(keyTPL))
	})

	w := httptest.New(a)
	res := w.HTML("/").Get()
	r.Contains(res.Body.String(), "something to say!")
}

const keyTPL = `<%= for (k, v) in flash { %>
	Flash:
		<%= k %>:<%= v %>
<% } %>
`

func Test_FlashRenderCustomKey(t *testing.T) {
	r := require.New(t)
	a := New(Options{})
	rr := render.New(render.Options{})

	a.GET("/", func(c Context) error {
		c.Flash().Add("something", "something to say!")
		return c.Render(http.StatusCreated, rr.String(keyTPL))
	})

	w := httptest.New(a)
	res := w.HTML("/").Get()
	r.Contains(res.Body.String(), "something to say!")
}

func Test_FlashRenderCustomKeyNotDefined(t *testing.T) {
	r := require.New(t)
	a := New(Options{})
	rr := render.New(render.Options{})

	a.GET("/", func(c Context) error {
		return c.Render(http.StatusCreated, rr.String(customKeyTPL))
	})

	w := httptest.New(a)
	res := w.HTML("/").Get()
	r.NotContains(res.Body.String(), "something to say!")
}

const customKeyTPL = `
	{{#each flash.other as |k value|}}
		{{value}}
	{{/each}}
`

func Test_FlashNotClearedOnRedirect(t *testing.T) {
	r := require.New(t)
	a := New(Options{})
	rr := render.New(render.Options{})

	a.GET("/flash", func(c Context) error {
		c.Flash().Add("success", "Antonio, you're welcome!")
		return c.Redirect(http.StatusSeeOther, "/")
	})

	a.GET("/", func(c Context) error {
		template := `Message: <%= flash["success"] %>`
		return c.Render(http.StatusCreated, rr.String(template))
	})

	w := httptest.New(a)
	res := w.HTML("/flash").Get()
	r.Equal(res.Code, http.StatusSeeOther)
	r.Equal(res.Location(), "/")

	res = w.HTML("/").Get()
	r.Contains(res.Body.String(), template.HTMLEscapeString("Antonio, you're welcome!"))

}


================================================
FILE: fs.go
================================================
package buffalo

import (
	"fmt"
	"io/fs"
	"os"
)

// FS wraps a directory and an embed FS that are expected to have the same contents.
// it prioritizes the directory FS and falls back to the embedded FS if the file cannot
// be found on disk. This is useful during development or when deploying with
// assets not embedded in the binary.
//
// Additionally FS hiddes any file named embed.go from the FS.
type FS struct {
	embed fs.FS
	dir   fs.FS
}

// NewFS returns a new FS that wraps the given directory and embedded FS.
// the embed.FS is expected to embed the same files as the directory FS.
func NewFS(embed fs.ReadDirFS, dir string) FS {
	return FS{
		embed: embed,
		dir:   os.DirFS(dir),
	}
}

// Open opens the named file.
//
// When Open returns an error, it should be of type *PathError with the Op
// field set to "open", the Path field set to name, and the Err field
// describing the problem.
//
// Open should reject attempts to open names that do not satisfy
// ValidPath(name), returning a *PathError with Err set to ErrInvalid or
// ErrNotExist.
func (f FS) Open(name string) (fs.File, error) {
	if name == "embed.go" {
		return nil, &fs.PathError{
			Op:   "open",
			Path: name,
			Err:  fs.ErrNotExist,
		}
	}
	file, err := f.getFile(name)
	if name == "." {
		// NOTE: It always returns the root from the "disk" instead
		// "embed". However, it could be fine since the the purpose
		// of buffalo.FS isn't supporting full featured filesystem.
		return rootFile{file}, err
	}
	return file, err
}

func (f FS) getFile(name string) (fs.File, error) {
	file, err := f.dir.Open(name)
	if err == nil {
		return file, nil
	}

	return f.embed.Open(name)
}

// rootFile wraps the "." directory for hidding the embed.go file.
type rootFile struct {
	fs.File
}

// ReadDir implements the fs.ReadDirFile interface.
func (f rootFile) ReadDir(n int) (entries []fs.DirEntry, err error) {
	dir, ok := f.File.(fs.ReadDirFile)
	if !ok {
		return nil, fmt.Errorf("%T is not a directory", f.File)
	}

	entries, err = dir.ReadDir(n)
	entries = hideEmbedFile(entries)
	return entries, err
}

func hideEmbedFile(entries []fs.DirEntry) []fs.DirEntry {
	result := make([]fs.DirEntry, 0, len(entries))

	for _, entry := range entries {
		if entry.Name() != "embed.go" {
			result = append(result, entry)
		}
	}
	return result
}


================================================
FILE: fs_test.go
================================================
package buffalo

import (
	"io"
	"io/fs"
	"testing"

	"github.com/gobuffalo/buffalo/internal/testdata/embedded"
	"github.com/stretchr/testify/require"
)

func Test_FS_Disallows_Parent_Folders(t *testing.T) {
	r := require.New(t)

	fsys := NewFS(embedded.FS(), "internal/testdata/disk")
	r.NotNil(fsys)

	f, err := fsys.Open("../panic.txt")
	r.ErrorIs(err, fs.ErrNotExist)
	r.Nil(f)

	f, err = fsys.Open("try/../to/../trick/../panic.txt")
	r.ErrorIs(err, fs.ErrNotExist)
	r.Nil(f)
}

func Test_FS_Hides_embed_go(t *testing.T) {
	r := require.New(t)

	fsys := NewFS(embedded.FS(), "internal/testdata/disk")
	r.NotNil(fsys)

	f, err := fsys.Open("embed.go")
	r.ErrorIs(err, fs.ErrNotExist)
	r.Nil(f)
}

func Test_FS_Prioritizes_Disk(t *testing.T) {
	r := require.New(t)

	fsys := NewFS(embedded.FS(), "internal/testdata/disk")
	r.NotNil(fsys)

	f, err := fsys.Open("file.txt")
	r.NoError(err)

	b, err := io.ReadAll(f)
	r.NoError(err)

	r.Equal("This file is on disk.", string(b))

	// should handle slash-separated path for all systems including Windows
	f, err = fsys.Open("under/sub/subfile")
	r.NoError(err)

	b, err = io.ReadAll(f)
	r.NoError(err)

	r.Equal("This file is on disk/sub.", string(b))
}

func Test_FS_Uses_Embed_If_No_Disk(t *testing.T) {
	r := require.New(t)

	fsys := NewFS(embedded.FS(), "internal/testdata/empty")
	r.NotNil(fsys)

	f, err := fsys.Open("file.txt")
	r.NoError(err)

	b, err := io.ReadAll(f)
	r.NoError(err)

	r.Equal("This file is embedded.", string(b))

	// should handle slash-separated path for all systems including Windows
	f, err = fsys.Open("under/sub/subfile")
	r.NoError(err)

	b, err = io.ReadAll(f)
	r.NoError(err)

	r.Equal("This file is on embedded/sub.", string(b))
}

func Test_FS_ReadDirFile(t *testing.T) {
	r := require.New(t)

	fsys := NewFS(embedded.FS(), "internal/testdata/disk")
	r.NotNil(fsys)

	f, err := fsys.Open(".")
	r.NoError(err)

	dir, ok := f.(fs.ReadDirFile)
	r.True(ok, "folder does not implement fs.ReadDirFile interface")

	// First read should return at most 1 file
	entries, err := dir.ReadDir(1)
	r.NoError(err)

	// The actual len will be 0 because the first file read is the embed.go file
	// this is counter-intuitive, but it's how the fs.ReadDirFile interface is specified;
	// if err == nil, just continue to call ReadDir until io.EOF is returned.
	r.LessOrEqual(len(entries), 1, "a call to ReadDir must at most return n entries")

	// Second read should return at most 2 files
	entries, err = dir.ReadDir(3)
	r.NoError(err)

	// The actual len will be 2 (file.txt & file2.txt + under/)
	r.LessOrEqual(len(entries), 3, "a call to ReadDir must at most return n entries")

	// trying to read next 2 files (none left)
	entries, err = dir.ReadDir(2)
	r.ErrorIs(err, io.EOF)
	r.Empty(entries)
}


================================================
FILE: go.mod
================================================
module github.com/gobuffalo/buffalo

go 1.25.0

require (
	github.com/BurntSushi/toml v1.2.1
	github.com/gobuffalo/events v1.4.3
	github.com/gobuffalo/flect v1.0.3
	github.com/gobuffalo/github_flavored_markdown v1.1.4
	github.com/gobuffalo/helpers v0.6.10
	github.com/gobuffalo/httptest v1.5.2
	github.com/gobuffalo/logger v1.0.7
	github.com/gobuffalo/plush/v5 v5.0.11
	github.com/gobuffalo/refresh v1.13.3
	github.com/gobuffalo/tags/v3 v3.1.4
	github.com/gorilla/handlers v1.5.1
	github.com/gorilla/mux v1.8.0
	github.com/gorilla/sessions v1.2.1
	github.com/joho/godotenv v1.4.0
	github.com/monoculum/formam v3.5.5+incompatible
	github.com/sirupsen/logrus v1.9.3
	github.com/spf13/cobra v1.6.1
	github.com/stretchr/testify v1.9.0
	golang.org/x/text v0.29.0
)

require (
	github.com/aymerick/douceur v0.2.0 // indirect
	github.com/davecgh/go-spew v1.1.1 // indirect
	github.com/fatih/color v1.13.0 // indirect
	github.com/fatih/structs v1.1.0 // indirect
	github.com/felixge/httpsnoop v1.0.1 // indirect
	github.com/fsnotify/fsnotify v1.6.0 // indirect
	github.com/gobuffalo/validate/v3 v3.3.3 // indirect
	github.com/gofrs/uuid v4.2.0+incompatible // indirect
	github.com/gorilla/css v1.0.1 // indirect
	github.com/gorilla/securecookie v1.1.1 // indirect
	github.com/inconshreveable/mousetrap v1.0.1 // indirect
	github.com/mattn/go-colorable v0.1.9 // indirect
	github.com/mattn/go-isatty v0.0.14 // indirect
	github.com/microcosm-cc/bluemonday v1.0.27 // indirect
	github.com/mitchellh/go-homedir v1.1.0 // indirect
	github.com/pmezard/go-difflib v1.0.0 // indirect
	github.com/sergi/go-diff v1.3.1 // indirect
	github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d // indirect
	github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e // indirect
	github.com/spf13/pflag v1.0.5 // indirect
	golang.org/x/net v0.45.0 // indirect
	golang.org/x/sys v0.36.0 // indirect
	golang.org/x/term v0.35.0 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
)


================================================
FILE: go.sum
================================================
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/gobuffalo/events v1.4.3 h1:JYDq7NbozP10zaN9Ijfem6Ozox2KacU2fU38RyquXM8=
github.com/gobuffalo/events v1.4.3/go.mod h1:2BwfpV5X63t8xkUcVqIv4IbyAobJazRSVu1F1pgf3rc=
github.com/gobuffalo/flect v0.3.0/go.mod h1:5pf3aGnsvqvCj50AVni7mJJF8ICxGZ8HomberC3pXLE=
github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4=
github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
github.com/gobuffalo/github_flavored_markdown v1.1.4 h1:WacrEGPXUDX+BpU1GM/Y0ADgMzESKNWls9hOTG1MHVs=
github.com/gobuffalo/github_flavored_markdown v1.1.4/go.mod h1:Vl9686qrVVQou4GrHRK/KOG3jCZOKLUqV8MMOAYtlso=
github.com/gobuffalo/helpers v0.6.10 h1:puKDCOrJ0EIq5ScnTRgKyvEZ05xQa+gwRGCpgoh6Ek8=
github.com/gobuffalo/helpers v0.6.10/go.mod h1:r52L6VSnByLJFOmURp1irvzgSakk7RodChi1YbGwk8I=
github.com/gobuffalo/httptest v1.5.2 h1:GpGy520SfY1QEmyPvaqmznTpG4gEQqQ82HtHqyNEreM=
github.com/gobuffalo/httptest v1.5.2/go.mod h1:FA23yjsWLGj92mVV74Qtc8eqluc11VqcWr8/C1vxt4g=
github.com/gobuffalo/logger v1.0.7 h1:LTLwWelETXDYyqF/ASf0nxaIcdEOIJNxRokPcfI/xbU=
github.com/gobuffalo/logger v1.0.7/go.mod h1:u40u6Bq3VVvaMcy5sRBclD8SXhBYPS0Qk95ubt+1xJM=
github.com/gobuffalo/plush/v5 v5.0.11 h1:FlThobIUreYx8fM4pH2Sug8TLXfNtmhqj6JO1Qs5jT8=
github.com/gobuffalo/plush/v5 v5.0.11/go.mod h1:C08u/VEqzzPBXFF/yqs40P/5Cvc/zlZsMzhCxXyWJmU=
github.com/gobuffalo/refresh v1.13.3 h1:HYQlI6RiqWUf2yzCXvUHAYqm9M9/teVnox+mjzo/9rQ=
github.com/gobuffalo/refresh v1.13.3/go.mod h1:NkzgLKZGk5suOvgvOD0/VALog0fH29Ib7fwym9JmRxA=
github.com/gobuffalo/tags/v3 v3.1.4 h1:X/ydLLPhgXV4h04Hp2xlbI2oc5MDaa7eub6zw8oHjsM=
github.com/gobuffalo/tags/v3 v3.1.4/go.mod h1:ArRNo3ErlHO8BtdA0REaZxijuWnWzF6PUXngmMXd2I0=
github.com/gobuffalo/validate/v3 v3.3.3 h1:o7wkIGSvZBYBd6ChQoLxkz2y1pfmhbI4jNJYh6PuNJ4=
github.com/gobuffalo/validate/v3 v3.3.3/go.mod h1:YC7FsbJ/9hW/VjQdmXPvFqvRis4vrRYFxr69WiNZw6g=
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/monoculum/formam v3.5.5+incompatible h1:iPl5csfEN96G2N2mGu8V/ZB62XLf9ySTpC8KRH6qXec=
github.com/monoculum/formam v3.5.5+incompatible/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d h1:yKm7XZV6j9Ev6lojP2XaIshpT4ymkqhMeSghO5Ps00E=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e h1:qpG93cPwA5f7s/ZPBJnGOYQNK/vKsaDaseuKT5Asee8=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=


================================================
FILE: handler.go
================================================
package buffalo

// Handler is the basis for all of Buffalo. A Handler
// will be given a Context interface that represents the
// give request/response. It is the responsibility of the
// Handler to handle the request/response correctly. This
// could mean rendering a template, JSON, etc... or it could
// mean returning an error.
/*
	func (c Context) error {
		return c.Render(http.StatusOK, render.String("Hello World!"))
	}

	func (c Context) error {
		return c.Redirect(http.StatusMovedPermanently, "http://github.com/gobuffalo/buffalo")
	}

	func (c Context) error {
		return c.Error(http.StatusUnprocessableEntity, fmt.Errorf("oops!!"))
	}
*/
type Handler func(Context) error


================================================
FILE: home.go
================================================
package buffalo

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

/* TODO: consider to split out Home (or Router, whatever) from App #road-to-v1
   Group and Domain based multi-homing are actually not an App if the concept
   of the App represents the application. The App should be only one for whole
   application.

   For an extreme example, App.Group().Stop() or even App.Group().Serve() are
   still valid function calls while they should not be allowed and the result
   could be strage.
*/

// Home is a container for Domains and Groups that independently serves a
// group of pages with its own Middleware and ErrorHandlers. It is usually
// a multi-homed server domain or group of paths under a certain prefix.
//
// While the App is for managing whole application life cycle along with its
// default Home, including initializing and stopping its all components such
// as listeners and long-running jobs, Home is only for a specific group of
// services to serve its service logic efficiently.
type Home struct {
	app     *App // will replace App.root
	appSelf *App // temporary while the App is in action.
	// replace Options' Name, Host, and Prefix
	name   string
	host   string
	prefix string

	// moved from App
	// Middleware returns the current MiddlewareStack for the App/Group.
	Middleware    *MiddlewareStack `json:"-"`
	ErrorHandlers ErrorHandlers    `json:"-"`
	router        *mux.Router
	filepaths     []string
}


================================================
FILE: internal/defaults/defaults.go
================================================
package defaults

func String(s1, s2 string) string {
	if s1 == "" {
		return s2
	}
	return s1
}

func Int(i1, i2 int) int {
	if i1 == 0 {
		return i2
	}
	return i1
}

func Int64(i1, i2 int64) int64 {
	if i1 == 0 {
		return i2
	}
	return i1
}

func Float32(i1, i2 float32) float32 {
	if i1 == 0.0 {
		return i2
	}
	return i1
}

func Float64(i1, i2 float64) float64 {
	if i1 == 0.0 {
		return i2
	}
	return i1
}


================================================
FILE: internal/defaults/defaults_test.go
================================================
package defaults

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func Test_String(t *testing.T) {
	a := assert.New(t)

	a.Equal(String("", "foo"), "foo")
	a.Equal(String("bar", "foo"), "bar")
	var s string
	a.Equal(String(s, "foo"), "foo")
}

func Test_Int(t *testing.T) {
	a := assert.New(t)

	a.Equal(Int(0, 1), 1)
	a.Equal(Int(2, 1), 2)
	var s int
	a.Equal(Int(s, 1), 1)
}

func Test_Int64(t *testing.T) {
	a := assert.New(t)

	a.Equal(Int64(0, 1), int64(1))
	a.Equal(Int64(2, 1), int64(2))
	var s int64
	a.Equal(Int64(s, 1), int64(1))
}

func Test_Float32(t *testing.T) {
	a := assert.New(t)

	a.Equal(Float32(0, 1), float32(1))
	a.Equal(Float32(2, 1), float32(2))
	var s float32
	a.Equal(Float32(s, 1), float32(1))
}

func Test_Float64(t *testing.T) {
	a := assert.New(t)

	a.Equal(Float64(0, 1), float64(1))
	a.Equal(Float64(2, 1), float64(2))
	var s float64
	a.Equal(Float64(s, 1), float64(1))
}


================================================
FILE: internal/env/env.go
================================================
// Package env provides environment variable utilities for Buffalo.
// This package replaces the github.com/gobuffalo/envy dependency.
package env

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/joho/godotenv"
)

// Load loads .env file(s) into environment.
// If no filenames are provided, it loads the .env file in the current directory.
func Load(filenames ...string) error {
	return godotenv.Load(filenames...)
}

// Get returns the value of the environment variable named by key.
// If the variable is not set or is empty, it returns the fallback value.
func Get(key, fallback string) string {
	if v := os.Getenv(key); v != "" {
		return v
	}
	return fallback
}

// MustGet returns the value of the environment variable named by key.
// It returns an error if the variable is not set or is empty.
func MustGet(key string) (string, error) {
	v := os.Getenv(key)
	if v == "" {
		return "", fmt.Errorf("environment variable %s is not set", key)
	}
	return v, nil
}

// Environ returns a copy of the environment variables.
func Environ() []string {
	return os.Environ()
}

// GoPath returns the GOPATH environment variable.
// If GOPATH is not set, it returns the default GOPATH: $HOME/go
func GoPath() string {
	if gp := os.Getenv("GOPATH"); gp != "" {
		return gp
	}
	home, _ := os.UserHomeDir()
	return filepath.Join(home, "go")
}

// Set sets the environment variable named by key to value.
func Set(key, value string) {
	os.Setenv(key, value)
}

// Temp executes f with temporarily modified environment variables.
// After f returns, the environment is restored to its original state.
func Temp(f func()) {
	oldEnv := os.Environ()
	defer func() {
		os.Clearenv()
		for _, e := range oldEnv {
			if i := strings.IndexByte(e, '='); i > 0 {
				os.Setenv(e[:i], e[i+1:])
			}
		}
	}()
	os.Clearenv()
	f()
}


================================================
FILE: internal/fakesmtp/connection.go
================================================
package fakesmtp

import (
	"bufio"
	"fmt"
	"net"
)

// Connection of a client with our server
type Connection struct {
	conn    net.Conn
	address string
	time    int64
	bufin   *bufio.Reader
	bufout  *bufio.Writer
}

// write something to the client on the connection
func (c *Connection) write(s string) {
	c.bufout.WriteString(s + "\r\n")
	c.bufout.Flush()
}

// read a string from the connected client
func (c *Connection) read() string {
	reply, err := c.bufin.ReadString('\n')

	if err != nil {
		fmt.Println("e ", err)
	}
	return reply
}


================================================
FILE: internal/fakesmtp/server.go
================================================
package fakesmtp

// This server is inspired by https://github.com/andrewarrow/jungle_smtp
// and most of its functionality have been taken from the original repo and updated to
// work better for buffalo.

import (
	"bufio"
	"net"
	"strings"
	"sync"
	"time"
)

// Server is our fake server that will be listening for SMTP connections.
type Server struct {
	Listener net.Listener
	messages []string
	mutex    sync.Mutex
}

// Start listens for connections on the given port
func (s *Server) Start(port string) error {
	for {
		conn, err := s.Listener.Accept()
		if err != nil {
			return err
		}

		s.Handle(&Connection{
			conn:    conn,
			address: conn.RemoteAddr().String(),
			time:    time.Now().Unix(),
			bufin:   bufio.NewReader(conn),
			bufout:  bufio.NewWriter(conn),
		})
	}
}

// Handle a connection from a client
func (s *Server) Handle(c *Connection) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	s.messages = append(s.messages, "")

	s.readHello(c)
	s.readSender(c)
	s.readRecipients(c)
	s.readData(c)

	c.conn.Close()
}

// Requests and notifies readed the Hello
func (s *Server) readHello(c *Connection) {
	c.write("220 Welcome")
	text := c.read()
	s.addMessageLine(text)

	c.write("250 Received")
}

// readSender reads the Sender from the connection
func (s *Server) readSender(c *Connection) {
	text := c.read()
	s.addMessageLine(text)
	c.write("250 Sender")
}

// readRecipients reads recipients from the connection
func (s *Server) readRecipients(c *Connection) {
	text := c.read()
	s.addMessageLine(text)

	c.write("250 Recipient")
	text = c.read()
	for strings.Contains(text, "RCPT") {
		s.addMessageLine(text)
		c.write("250 Recipient")
		text = c.read()
	}
}

// readData reads the message data.
func (s *Server) readData(c *Connection) {
	c.write("354 Ok Send data ending with <CRLF>.<CRLF>")

	for {
		text := c.read()
		bytes := []byte(text)
		s.addMessageLine(text)
		// 46 13 10
		if bytes[0] == 46 && bytes[1] == 13 && bytes[2] == 10 {
			break
		}
	}
	c.write("250 server has transmitted the message")
}

// addMessageLine ads a line to the last message
func (s *Server) addMessageLine(text string) {
	s.messages[len(s.Messages())-1] = s.LastMessage() + text
}

// LastMessage returns the last message on the server
func (s *Server) LastMessage() string {
	if len(s.Messages()) == 0 {
		return ""
	}

	return s.Messages()[len(s.Messages())-1]
}

// Messages returns the list of messages on the server
func (s *Server) Messages() []string {
	return s.messages
}

// Clear the server messages
func (s *Server) Clear() {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	s.messages = []string{}
}

// New returns a pointer to a new Server instance listening on the given port.
func New(port string) (*Server, error) {
	s := &Server{messages: []string{}}

	listener, err := net.Listen("tcp", "0.0.0.0:"+port)
	if err != nil {
		return s, err
	}
	s.Listener = listener
	return s, nil
}


================================================
FILE: internal/httpx/content_type.go
================================================
package httpx

import (
	"net/http"
	"strings"

	"github.com/gobuffalo/buffalo/internal/defaults"
)

func ContentType(req *http.Request) string {
	ct := defaults.String(req.Header.Get("Content-Type"), req.Header.Get("Accept"))
	ct = strings.TrimSpace(ct)
	var cts []string
	if strings.Contains(ct, ",") {
		cts = strings.Split(ct, ",")
	} else {
		cts = strings.Split(ct, ";")
	}
	for _, c := range cts {
		c = strings.TrimSpace(c)
		if strings.HasPrefix(c, "*/*") {
			continue
		}
		return strings.ToLower(c)
	}
	if ct == "*/*" {
		return ""
	}
	return ct
}


================================================
FILE: internal/httpx/content_type_test.go
================================================
package httpx

import (
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/require"
)

func Test_ContentType(t *testing.T) {
	r := require.New(t)

	table := []struct {
		Header   string
		Value    string
		Expected string
	}{
		{"content-type", "a", "a"},
		{"Content-Type", "c,d", "c"},
		{"Content-Type", "e;f", "e"},
		{"Content-Type", "", ""},
		{"Accept", "", ""},
		{"Accept", "*/*", ""},
		{"Accept", "*/*;q=0.5, text/javascript, application/javascript, application/ecmascript, application/x-ecmascript", "text/javascript"},
		{"accept", "text/javascript,application/javascript,application/ecmascript,application/x-ecmascript", "text/javascript"},
	}

	for _, tt := range table {
		req := httptest.NewRequest("GET", "/", nil)
		req.Header.Set(tt.Header, tt.Value)
		r.Equal(tt.Expected, ContentType(req))
	}
}


================================================
FILE: internal/meta/meta.go
================================================
// Package meta provides application metadata for Buffalo's plugin system.
package meta

import (
	"os"
	"path/filepath"

	"github.com/BurntSushi/toml"
)

// BuildTags is a type alias for build tags used by plugins.
type BuildTags []string

// App holds metadata about the Buffalo application.
type App struct {
	Root    string `toml:"-"`
	WithPop bool   `toml:"with_pop"`
}

// New creates App metadata for the given root path.
// If root is "." or empty, uses current working directory.
// First tries to load WithPop from config/buffalo-app.toml,
// then falls back to detecting database.yml.
func New(root string) App {
	if root == "." || root == "" {
		if pwd, err := os.Getwd(); err == nil {
			root = pwd
		}
	}

	app := App{Root: root}

	tomlPath := filepath.Join(root, "config", "buffalo-app.toml")
	if _, err := os.Stat(tomlPath); err == nil {
		// TOML config exists, use it and skip auto-detection
		toml.DecodeFile(tomlPath, &app)
		return app
	}

	// No TOML config, auto-detect from filesystem
	if _, err := os.Stat(filepath.Join(root, "database.yml")); err == nil {
		app.WithPop = true
	}

	return app
}


================================================
FILE: internal/meta/meta_test.go
================================================
package meta

import (
	"os"
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/require"
)

func Test_New_Defaults(t *testing.T) {
	r := require.New(t)

	app := New("")
	r.NotEmpty(app.Root)
	r.False(app.WithPop)

	app = New(".")
	r.NotEmpty(app.Root)
}

func Test_New_With_DatabaseYML(t *testing.T) {
	r := require.New(t)

	tmp := t.TempDir()
	dbYML := filepath.Join(tmp, "database.yml")
	r.NoError(os.WriteFile(dbYML, []byte("test"), 0644))

	app := New(tmp)
	r.Equal(tmp, app.Root)
	r.True(app.WithPop)
}

func Test_New_With_TOML(t *testing.T) {
	r := require.New(t)

	tmp := t.TempDir()
	configDir := filepath.Join(tmp, "config")
	r.NoError(os.MkdirAll(configDir, 0755))

	tomlContent := `with_pop = true`
	tomlPath := filepath.Join(configDir, "buffalo-app.toml")
	r.NoError(os.WriteFile(tomlPath, []byte(tomlContent), 0644))

	app := New(tmp)
	r.Equal(tmp, app.Root)
	r.True(app.WithPop)
}

func Test_New_TOML_Priority_Over_DatabaseYML(t *testing.T) {
	r := require.New(t)

	tmp := t.TempDir()

	// Create both files
	configDir := filepath.Join(tmp, "config")
	r.NoError(os.MkdirAll(configDir, 0755))

	tomlContent := `with_pop = false`
	tomlPath := filepath.Join(configDir, "buffalo-app.toml")
	r.NoError(os.WriteFile(tomlPath, []byte(tomlContent), 0644))

	dbYML := filepath.Join(tmp, "database.yml")
	r.NoError(os.WriteFile(dbYML, []byte("test"), 0644))

	// TOML should take priority
	app := New(tmp)
	r.False(app.WithPop)
}

func Test_New_No_Files(t *testing.T) {
	r := require.New(t)

	tmp := t.TempDir()

	app := New(tmp)
	r.Equal(tmp, app.Root)
	r.False(app.WithPop)
}


================================================
FILE: internal/nulls/nulls.go
================================================
package nulls

import (
	"database/sql/driver"
	"encoding/json"
	"time"
)

// Time represents a time.Time that may be null.
// It implements sql.Scanner and driver.Valuer interfaces.
type Time struct {
	Time  time.Time
	Valid bool // Valid is true if Time is not NULL
}

// Scan implements the sql.Scanner interface.
func (t *Time) Scan(value any) error {
	if value == nil {
		t.Time, t.Valid = time.Time{}, false
		return nil
	}
	t.Valid = true
	switch v := value.(type) {
	case time.Time:
		t.Time = v
	case []byte:
		return t.Parse(string(v))
	case string:
		return t.Parse(v)
	}
	return nil
}

// Parse tries to parse the string as a time using multiple formats.
func (t *Time) Parse(s string) error {
	formats := []string{
		time.RFC3339,
		"2006-01-02 15:04:05",
		"2006-01-02",
		"01/02/2006",
		"01/02/2006 15:04:05",
		"2006-01-02T15:04:05",
		time.RFC3339Nano,
	}

	for _, format := range formats {
		if tt, err := time.Parse(format, s); err == nil {
			t.Time = tt
			return nil
		}
	}
	return nil
}

// Value implements the driver.Valuer interface.
func (t Time) Value() (driver.Value, error) {
	if !t.Valid {
		return nil, nil
	}
	return t.Time, nil
}

// UnmarshalJSON implements json.Unmarshaler.
func (t *Time) UnmarshalJSON(data []byte) error {
	if string(data) == "null" {
		t.Time, t.Valid = time.Time{}, false
		return nil
	}
	if len(data) >= 2 && data[0] == '"' && data[len(data)-1] == '"' {
		data = data[1 : len(data)-1]
	}
	return t.Parse(string(data))
}

// MarshalJSON implements json.Marshaler.
func (t Time) MarshalJSON() ([]byte, error) {
	if !t.Valid {
		return []byte("null"), nil
	}
	return json.Marshal(t.Time)
}

// String implements fmt.Stringer.
func (t Time) String() string {
	if !t.Valid {
		return ""
	}
	return t.Time.String()
}

// NewTime returns a new, properly initialized
// Time object.
func NewTime(t time.Time) Time {
	return Time{
		Time:  t,
		Valid: true,
	}
}


================================================
FILE: internal/templates/error.dev.html
================================================
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
        <%= status %> - ERROR!
    </title>
    <style>
        html {
            font-family: sans-serif;
            -webkit-text-size-adjust: 100%;
            -ms-text-size-adjust: 100%
        }

        body {
            margin: 0
        }

        header {
            display: block
        }

        a {
            background-color: transparent
        }

        a:active,
        a:hover {
            outline: 0
        }

        h1 {
            margin: .67em 0;
            font-size: 2em
        }

        img {
            border: 0
        }

        pre {
            overflow: auto
        }

        code,
        pre {
            font-family: monospace, monospace;
            font-size: 1em
        }

        table {
            border-spacing: 0;
            border-collapse: collapse
        }

        td,
        th {
            padding: 0
        }

        @media print {
            * {
                color: #000 !important;
                text-shadow: none !important;
                background: 0 0 !important;
                -webkit-box-shadow: none !important;
                box-shadow: none !important
            }

            a,
            a:visited {
                text-decoration: underline
            }

            a[href]:after {
                content: " ("attr(href) ")"
            }

            pre {
                border: 1px solid #999;
                page-break-inside: avoid
            }

            thead {
                display: table-header-group
            }

            img,
            tr {
                page-break-inside: avoid
            }

            img {
                max-width: 100% !important
            }

            h3 {
                orphans: 3;
                widows: 3
            }

            h3 {
                page-break-after: avoid
            }

            .table {
                border-collapse: collapse !important
            }

            .table td,
            .table th {
                background-color: #fff !important
            }
        }

        @font-face {
            font-family: 'Glyphicons Halflings';
            src: url(../fonts/glyphicons-halflings-regular.eot);
            src: url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'), url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'), url(../fonts/glyphicons-halflings-regular.woff) format('woff'), url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'), url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')
        }

        * {
            -webkit-box-sizing: border-box;
            -moz-box-sizing: border-box;
            box-sizing: border-box
        }

        html {
            font-size: 10px;
            -webkit-tap-highlight-color: rgba(0, 0, 0, 0)
        }

        body {
            font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            font-size: 14px;
            line-height: 1.42857143;
            color: #333;
            background-color: #fff
        }

        a {
            color: #337ab7;
            text-decoration: none
        }

        a:focus,
        a:hover {
            color: #23527c;
            text-decoration: underline
        }

        a:focus {
            outline: 5px auto -webkit-focus-ring-color;
            outline-offset: -2px
        }

        img {
            vertical-align: middle
        }

        h1,
        h3 {
            font-family: inherit;
            font-weight: 500;
            line-height: 1.1;
            color: inherit
        }

        h1,
        h3 {
            margin-top: 20px;
            margin-bottom: 10px
        }

        h1 {
            font-size: 36px
        }

        h3 {
            font-size: 24px
        }

        code,
        pre {
            font-family: Menlo, Monaco, Consolas, "Courier New", monospace
        }

        code {
            padding: 2px 4px;
            font-size: 90%;
            color: #c7254e;
            background-color: #f9f2f4;
            border-radius: 4px
        }

        pre {
            display: block;
            padding: 9.5px;
            margin: 0 0 10px;
            font-size: 13px;
            line-height: 1.42857143;
            color: #333;
            word-break: break-all;
            word-wrap: break-word;
            background-color: #f5f5f5;
            border: 1px solid #ccc;
            border-radius: 4px
        }

        .container {
            padding-right: 15px;
            padding-left: 15px;
            margin-right: auto;
            margin-left: auto
        }

        @media (min-width:768px) {
            .container {
                width: 750px
            }
        }

        @media (min-width:992px) {
            .container {
                width: 970px
            }
        }

        @media (min-width:1200px) {
            .container {
                width: 1170px
            }
        }

        .row {
            margin-right: -15px;
            margin-left: -15px
        }

        .col-md-1,
        .col-md-10,
        .col-md-12,
        .col-sm-2,
        .col-sm-6,
        .col-xs-3,
        .col-xs-7 {
            position: relative;
            min-height: 1px;
            padding-right: 15px;
            padding-left: 15px
        }

        .col-xs-3,
        .col-xs-7 {
            float: left
        }

        .col-xs-7 {
            width: 58.33333333%
        }

        .col-xs-3 {
            width: 25%
        }

        @media (min-width:768px) {

            .col-sm-2,
            .col-sm-6 {
                float: left
            }

            .col-sm-6 {
                width: 50%
            }

            .col-sm-2 {
                width: 16.66666667%
            }
        }

        @media (min-width:992px) {

            .col-md-1,
            .col-md-10,
            .col-md-12 {
                float: left
            }

            .col-md-12 {
                width: 100%
            }

            .col-md-10 {
                width: 83.33333333%
            }

            .col-md-1 {
                width: 8.33333333%
            }
        }

        table {
            background-color: transparent
        }

        th {
            text-align: left
        }

        .table {
            width: 100%;
            max-width: 100%;
            margin-bottom: 20px
        }

        .table>tbody>tr>td,
        .table>thead>tr>th {
            padding: 8px;
            line-height: 1.42857143;
            vertical-align: top;
            border-top: 1px solid #ddd
        }

        .table>thead>tr>th {
            vertical-align: bottom;
            border-bottom: 2px solid #ddd
        }

        .table>thead:first-child>tr:first-child>th {
            border-top: 0
        }

        .table-striped>tbody>tr:nth-of-type(odd) {
            background-color: #f9f9f9
        }

        .container:after,
        .container:before,
        .row:after,
        .row:before {
            display: table;
            content: " "
        }

        .container:after,
        .row:after {
            clear: both
        }

        @-ms-viewport {
            width: device-width
        }

        h1 {
            margin-top: 20px
        }

        * {
            -webkit-box-sizing: border-box;
            -moz-box-sizing: border-box;
            box-sizing: border-box
        }

        body {
            font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            font-size: 14px;
            line-height: 1.42857143;
            color: #333;
            background-color: #fff;
            margin: 0
        }

        h1 {
            margin-bottom: 10px;
            font-family: inherit;
            font-weight: 500;
            line-height: 1.1;
            color: inherit
        }

        .table {
            margin-bottom: 20px
        }

        h1 {
            font-size: 36px
        }

        a {
            color: #337ab7;
            text-decoration: none
        }

        a:hover {
            color: #23527c
        }

        .container {
            padding-right: 15px;
            padding-left: 15px;
            margin-right: auto;
            margin-left: auto
        }

        @media (min-width:768px) {
            .container {
                width: 750px
            }
        }

        @media (min-width:992px) {
            .container {
                width: 970px
            }
        }

        @media (min-width:1200px) {
            .container {
                width: 1170px
            }
        }

        .table {
            width: 100%;
            max-width: 100%;
            background-color: transparent;
            border-spacing: 0;
            border-collapse: collapse
        }

        .table-striped>tbody {
            background-color: #f9f9f9
        }

        .table>tbody>tr>td,
        .table>thead>tr>th {
            padding: 8px;
            line-height: 1.42857143;
            vertical-align: top;
            border-top: 1px solid #ddd
        }

        .table>thead>tr>th {
            border-top: 0;
            vertical-align: bottom;
            border-bottom: 2px solid #ddd;
            text-align: left
        }

        code {
            padding: 2px 4px;
            font-size: 90%;
            color: #c7254e;
            background-color: #f9f2f4;
            border-radius: 4px;
            font-family: Menlo, Monaco, Consolas, "Courier New", monospace
        }

        .row {
            margin-right: -15px;
            margin-left: -15px
        }

        .col-md-10 {
            float: left;
            position: relative;
            min-height: 1px;
            padding-right: 15px;
            padding-left: 15px
        }

        .col-md-10 {
            width: 83.33333333%
        }

        img {
            vertical-align: middle;
            border: 0
        }

        .container {
            min-width: 320px
        }

        body {
            font-family: helvetica
        }

        table {
            font-size: 14px
        }

        table.table tbody tr td {
            border-top: 0;
            border-bottom: 1px dotted #ddd;
            padding: 2px;
        }

        pre {
            white-space: pre-wrap;
            margin-bottom: 10px;
            max-height: 275px;
            overflow: scroll
        }

        header {
            background-color: #ed605e;
            padding: 10px 20px;
            box-sizing: border-box
        }

        .logo img {
            width: 80px
        }

        .titles h1 {
            font-size: 30px;
            font-weight: 300;
            color: #fff;
            margin: 24px 0
        }

        .content h3 {
            color: gray;
            margin: 25px 0
        }

        .foot {
            padding: 5px 0 20px;
            text-align: right;
            color: #c5c5c5;
            font-weight: 300
        }

        .foot a {
            color: #8b8b8b;
            text-decoration: underline
        }

        .centered {
            text-align: center
        }

        @media all and (max-width:500px) {
            .titles h1 {
                font-size: 25px;
                margin: 26px 0
            }
        }

        @media all and (max-width:530px) {
            .titles h1 {
                font-size: 20px;
                margin: 24px 0
            }

            .logo {
                padding: 0
            }

            .logo img {
                width: 100%;
                max-width: 80px
            }
        }
    </style>
</head>

<body>
    <header>
        <div class="container">
            <div class="row">
                <div class="col-md-1 col-sm-2 col-xs-3 logo">
                    <a href="/"><img src="https://gobuffalo.io/assets/images/logo_med.png" alt=""></a>
                </div>
                <div class="col-md-10 col-sm-6 col-xs-7 titles">
                    <h1>
                        <%= status %> - ERROR!
                    </h1>
                </div>
            </div>
        </div>
    </header>

    <div class="container content">
        <div class="row">
            <div class="col-md-12">
                <h3>Error Trace</h3>
                <pre><%= error %></pre>

                <h3>Context</h3>
                <pre><%= inspect(context) %></pre>

                <h3>Parameters</h3>
                <pre><%= inspect(params) %></pre>

                <h3>Headers</h3>
                <pre><%= inspect(headers) %></pre>

                <h3>Form</h3>
                <pre><%= inspect(posted_form) %></pre>

                <h3>Routes</h3>
                <table class="table table-striped">
                    <thead>
                        <tr text-align="left">
                            <th class="centered">METHOD</th>
                            <th>PATH</th>
                            <th>NAME</th>
                            <th>HANDLER</th>
                        </tr>
                    </thead>
                    <tbody>

                        <%= for (r) in routes { %>
                            <tr>
                                <td class="centered">
                                    <%= r.Method %>
                                </td>
                                <td>
                                    <%= if (r.Method !="GET" || r.Path ~="{" ) { %>
                                        <%= r.Path %>
                                            <% } else { %>
                                                <a href="<%= r.Path %>">
                                                    <%= r.Path %>
                                                </a>
                                                <% } %>
                                </td>
                                <td>
                                    <%= r.PathName %>
                                </td>
                                <td><code><%= r.HandlerName %></code></td>
                            </tr>
                            <% } %>

                    </tbody>
                </table>
            </div>
        </div>
        <div class="foot"> <span> Powered by <a href="http://gobuffalo.io/">gobuffalo.io</a></span></div>
    </div>
</body>

</html>

================================================
FILE: internal/templates/error.prod.html
================================================
<!DOCTYPE html>
<html>
<head>
    <style>
        h1,
        p.powered {
            text-align: center
        }

        body {
            background: #ECECEC;
            padding-top: 25px;
            font-family: helvetica neue, helvetica, sans-serif;
            color: #333
        }

        .card {
            box-sizing: border-box;
            width: 440px;
            min-width: 270px;
            margin: 0 auto;
            padding: 10px 25px 35px 10px;
            background: #FFF;
            box-shadow: 0 2px 4px 0 rgba(185, 185, 185, .28);
            border-radius: 5px
        }

        .card p {
            max-width: 320px;
            margin: 15px auto
        }

        h1 {
            font-size: 22px
        }

        hr {
            border: .5px solid #D72727;
            width: 180px
        }

        p.powered {
            font-family: HelveticaNeue-Light;
            font-size: 12px;
            color: #333
        }

        @media (max-width:600px) {
            .card {
                width: 100%;
                display: block
            }
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="card">
            <h1>We're Sorry!</h1>
            <hr>
            <p>It looks like something went wrong! Don't worry, we are aware of the problem and are looking into it.</p>
            <p>Sorry if this has caused you any problems. Please check back again later.</p>
        </div>

        <p class="powered">powered by <a href="https://gobuffalo.io">gobuffalo.io</a></p>
    </div>
</body>

</html>

================================================
FILE: internal/templates/notfound.prod.html
================================================
<!DOCTYPE html>
<html>

<head>
    <style>
        h1,
        p.powered {
            text-align: center
        }

        body {
            background: #ECECEC;
            padding-top: 25px;
            font-family: helvetica neue, helvetica, sans-serif;
            color: #333
        }

        .card {
            box-sizing: border-box;
            width: 440px;
            min-width: 270px;
            margin: 0 auto;
            padding: 10px 25px 35px 10px;
            background: #FFF;
            box-shadow: 0 2px 4px 0 rgba(185, 185, 185, .28);
            border-radius: 5px
        }

        .card p {
            max-width: 320px;
            margin: 15px auto
        }

        h1 {
            font-size: 22px
        }

        hr {
            border: .5px solid #1272E2;
            width: 180px
        }

        p.powered {
            font-family: HelveticaNeue-Light;
            font-size: 12px;
            color: #333
        }

        @media (max-width:600px) {
            .card {
                width: 100%;
                display: block
            }
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="card">
            <h1>Not Found</h1>
            <hr>
            <p>The page you're looking for does not exist, you may have mistyped the address or the page may have been
                moved.</p>
        </div>

        <p class="powered">powered by <a href="https://gobuffalo.io">gobuffalo.io</a></p>
    </div>
</body>

</html>

================================================
FILE: internal/testdata/disk/file.txt
================================================
This file is on disk.

================================================
FILE: internal/testdata/disk/file2.txt
================================================


================================================
FILE: internal/testdata/disk/under/sub/subfile
================================================
This file is on disk/sub.

================================================
FILE: internal/testdata/embedded/embed.go
================================================
package embedded

import (
	"embed"
)

//go:embed *
var files embed.FS

func FS() embed.FS {
	return files
}


================================================
FILE: internal/testdata/embedded/file.txt
================================================
This file is embedded.

================================================
FILE: internal/testdata/embedded/under/sub/subfile
================================================
This file is on embedded/sub.

================================================
FILE: internal/testdata/panic.txt
================================================
This file must not be accessible from buffalo.FS.

================================================
FILE: logger.go
================================================
package buffalo

import (
	"github.com/gobuffalo/logger"
)

// Logger interface is used throughout Buffalo
// apps to log a whole manner of things.
type Logger = logger.FieldLogger


================================================
FILE: mail/README.md
================================================
# github.com/gobuffalo/buffalo/mail

This package is intended to allow easy Email sending with Buffalo, it allows you to define your custom `mail.Sender` for the provider you would like to use.

## Generator

```bash
buffalo generate mailer welcome_email
```

## Example Usage

```go
//actions/mail.go
package x

import (
    "log"
    "net/http"

    "github.com/gobuffalo/buffalo/render"
    "github.com/gobuffalo/buffalo/internal/env"
    "github.com/gobuffalo/plush"
    "github.com/gobuffalo/buffalo/mail"
    "errors"
    "gitlab.com/wawandco/app/models"
)

var smtp mail.Sender
var r *render.Engine

func init() {

    //Pulling config from the env.
    port := env.Get("SMTP_PORT", "1025")
    host := env.Get("SMTP_HOST", "localhost")
    user := env.Get("SMTP_USER", "")
    password := env.Get("SMTP_PASSWORD", "")

    var err error
    smtp, err = mail.NewSMTPSender(host, port, user, password)

    if err != nil {
        log.Fatal(err)
    }

    //The rendering engine, this is usually generated inside actions/render.go in your buffalo app.
    r = render.New(render.Options{
        TemplatesFS:   mailTemplates,
    })
}

//SendContactMessage Sends contact message to contact@myapp.com
func SendContactMessage(c *models.Contact) error {

    //Creates a new message
    m := mail.NewMessage()
    m.From = "sender@myapp.com"
    m.Subject = "New Contact"
    m.To = []string{"contact@myapp.com"}

    // Data that will be used inside the templates when rendering.
    data := map[string]interface{}{
        "contact": c,
    }

    // You can add multiple bodies to the message you're creating to have content-types alternatives.
    err := m.AddBodies(data, r.HTML("mail/contact.html"), r.Plain("mail/contact.txt"))

    if err != nil {
        return err
    }

    err = smtp.Send(m)
    if err != nil {
        return err
    }

    return nil
}

```

This `SendContactMessage` could be called by one of your actions, p.e. the action that handles your contact form submission.

```go
//actions/contact.go
...

func ContactFormHandler(c buffalo.Context) error {
    contact := &models.Contact{}
    c.Bind(contact)

    //Calling to send the message
    SendContactMessage(contact)
    return c.Redirect(http.StatusFound, "contact/thanks")
}
...
```

If you're using Gmail or need to configure your SMTP connection you can use the Dialer property on the SMTPSender, p.e: (for Gmail)

```go
...
var smtp mail.Sender

func init() {
    port := env.Get("SMTP_PORT", "465")
    // or 587 with TLS

    host := env.Get("SMTP_HOST", "smtp.gmail.com")
    user := env.Get("SMTP_USER", "your@email.com")
    password := env.Get("SMTP_PASSWORD", "yourp4ssw0rd")

    var err error
    sender, err := mail.NewSMTPSender(host, port, user, password)
    sender.Dialer.SSL = true

    //or if TLS
    sender.Dialer.TLSConfig = &tls.Config{...}

    smtp = sender
}
...
```


================================================
FILE: mail/attachment.go
================================================
package mail

import "io"

// Attachment are files added into a email message
type Attachment struct {
	Name        string
	Reader      io.Reader
	ContentType string
	Embedded    bool
}


================================================
FILE: mail/body.go
================================================
package mail

// Body represents one of the bodies in the Message could be main or alternative
type Body struct {
	Content     string
	ContentType string
}


================================================
FILE: mail/dialer.go
================================================
// Portions of this code are derived from the go-mail/mail project.
// https://github.com/go-mail/mail (MIT License)

package mail

import (
	"crypto/tls"
	"fmt"
	"io"
	"net"
	"net/smtp"
	"strings"
	"time"
)

// Dialer connects to an SMTP server and sends emails.
type Dialer struct {
	Host     string
	Port     int
	Username string
	Password string
	Auth     smtp.Auth
	// SSL defines whether an SSL connection is used. It should be false in
	// most cases since the authentication mechanism should use the STARTTLS
	// extension instead.
	SSL bool
	// TLSConfig represents the TLS configuration used for the TLS (when the
	// STARTTLS extension is used) or SSL connection.
	TLSConfig *tls.Config
	// StartTLSPolicy represents the TLS security level required to communicate
	// with the SMTP server. Defaults to opportunistic STARTTLS.
	StartTLSPolicy StartTLSPolicy
	// LocalName is the hostname sent to the SMTP server with the HELO command.
	// By default, "localhost" is sent.
	LocalName string
	// Timeout to use for read/write operations. Defaults to 10 seconds, can
	// be set to 0 to disable timeouts.
	Timeout time.Duration
	// Whether we should retry mailing if the connection returned an error.
	RetryFailure bool
}

func newDialer(host string, port int, username, password string) *Dialer {
	return &Dialer{
		Host:         host,
		Port:         port,
		Username:     username,
		Password:     password,
		SSL:          port == 465,
		Timeout:      10 * time.Second,
		RetryFailure: true,
	}
}

// NetDialTimeout specifies the DialTimeout function to establish a connection
// to the SMTP server. This can be used to override dialing in the case that a
// proxy or other special behavior is needed.
var NetDialTimeout = net.DialTimeout

func (d *Dialer) dial() (sendCloser, error) {
	conn, err := NetDialTimeout("tcp", addr(d.Host, d.Port), d.Timeout)
	if err != nil {
		return nil, err
	}

	if d.SSL {
		conn = tlsClient(conn, d.tlsConfig())
	}

	c, err := smtpNewClient(conn, d.Host)
	if err != nil {
		return nil, err
	}

	if d.Timeout > 0 {
		conn.SetDeadline(time.Now().Add(d.Timeout))
	}

	if d.LocalName != "" {
		if err := c.Hello(d.LocalName); err != nil {
			return nil, err
		}
	}

	if !d.SSL && d.StartTLSPolicy != noStartTLS {
		ok, _ := c.Extension("STARTTLS")
		if !ok && d.StartTLSPolicy == mandatoryStartTLS {
			err := startTLSUnsupportedError{Policy: d.StartTLSPolicy}
			return nil, err
		}

		if ok {
			if err := c.StartTLS(d.tlsConfig()); err != nil {
				c.Close()
				return nil, err
			}
		}
	}

	if d.Auth == nil && d.Username != "" {
		if ok, auths := c.Extension("AUTH"); ok {
			if strings.Contains(auths, "CRAM-MD5") {
				d.Auth = smtp.CRAMMD5Auth(d.Username, d.Password)
			} else if strings.Contains(auths, "LOGIN") &&
				!strings.Contains(auths, "PLAIN") {
				d.Auth = &loginAuth{
					username: d.Username,
					password: d.Password,
					host:     d.Host,
				}
			} else {
				d.Auth = smtp.PlainAuth("", d.Username, d.Password, d.Host)
			}
		}
	}

	if d.Auth != nil {
		if err = c.Auth(d.Auth); err != nil {
			c.Close()
			return nil, err
		}
	}

	return &smtpSender{c, conn, d}, nil
}

func (d *Dialer) tlsConfig() *tls.Config {
	if d.TLSConfig == nil {
		return &tls.Config{ServerName: d.Host}
	}
	return d.TLSConfig
}

// StartTLSPolicy represents the TLS security level required to communicate
// with an SMTP server.
type StartTLSPolicy int

const (
	opportunisticStartTLS StartTLSPolicy = iota
	mandatoryStartTLS
	noStartTLS = -1
)

func (policy *StartTLSPolicy) String() string {
	switch *policy {
	case opportunisticStartTLS:
		return "OpportunisticStartTLS"
	case mandatoryStartTLS:
		return "MandatoryStartTLS"
	case noStartTLS:
		return "NoStartTLS"
	default:
		return fmt.Sprintf("StartTLSPolicy:%v", *policy)
	}
}

type startTLSUnsupportedError struct {
	Policy StartTLSPolicy
}

func (e startTLSUnsupportedError) Error() string {
	return "gomail: " + e.Policy.String() + " required, but SMTP server does not support STARTTLS"
}

func addr(host string, port int) string {
	return fmt.Sprintf("%s:%d", host, port)
}

func (d *Dialer) dialAndSend(m ...*smtpMessage) error {
	s, err := d.dial()
	if err != nil {
		return err
	}
	defer s.Close()

	for _, err := range sendSMTP(s, m...) {
		if err != nil {
			return err
		}
	}

	return nil
}

type smtpSender struct {
	smtpClient
	conn net.Conn
	d    *Dialer
}

func (c *smtpSender) retryError(err error) bool {
	if !c.d.RetryFailure {
		return false
	}

	if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
		return true
	}

	return err == io.EOF
}

func (c *smtpSender) Send(from string, to []string, msg io.WriterTo) error {
	if c.d.Timeout > 0 {
		c.conn.SetDeadline(time.Now().Add(c.d.Timeout))
	}

	if err := c.Mail(from); err != nil {
		if c.retryError(err) {
			sc, derr := c.d.dial()
			if derr == nil {
				if s, ok := sc.(*smtpSender); ok {
					*c = *s
					return c.Send(from, to, msg)
				}
			}
		}

		return err
	}

	for _, addr := range to {
		if err := c.Rcpt(addr); err != nil {
			return err
		}
	}

	w, err := c.Data()
	if err != nil {
		return err
	}

	if _, err = msg.WriteTo(w); err != nil {
		w.Close()
		return err
	}

	return w.Close()
}

func (c *smtpSender) Close() error {
	return c.Quit()
}

// Stubbed out for tests.
var (
	tlsClient     = tls.Client
	smtpNewClient = func(conn net.Conn, host string) (smtpClient, error) {
		return smtp.NewClient(conn, host)
	}
)

type smtpClient interface {
	Hello(string) error
	Extension(string) (bool, string)
	StartTLS(*tls.Config) error
	Auth(smtp.Auth) error
	Mail(string) error
	Rcpt(string) error
	Data() (io.WriteCloser, error)
	Quit() error
	Close() error
}

type sendCloser interface {
	sender
	Close() error
}

type sender interface {
	Send(from string, to []string, msg io.WriterTo) error
}


================================================
FILE: mail/mail.go
================================================
// Package mail provides email sending functionality for Buffalo applications.
// It supports SMTP delivery with customizable configuration including TLS/SSL,
// authentication, and batch sending capabilities.
//
// Portions of the SMTP implementation are derived from the go-mail/mail project
// (https://github.com/go-mail/mail) under the MIT License.
//
// TODO: Properly encode filenames for non-ASCII characters.
// TODO: Properly encode email addresses for non-ASCII characters.
// TODO: Test embedded files and attachments for their existence before sending.
// TODO: Allow supplying an io.Reader when embedding and attaching files.
package mail

import (
	"context"
	"maps"
	"sync"

	"github.com/gobuffalo/buffalo"
	"github.com/gobuffalo/buffalo/render"
)

// NewMessage builds a new message.
func NewMessage() Message {
	return Message{
		Context: context.Background(),
		Headers: map[string]string{},
		Data:    render.Data{},
		moot:    &sync.RWMutex{},
	}
}

// NewFromData builds a new message with raw template data given
func NewFromData(data render.Data) Message {
	m := NewMessage()
	m.Data = maps.Clone(data)
	return m
}

// New builds a new message with the current buffalo.Context
func New(c buffalo.Context) Message {
	m := NewFromData(c.Data())
	m.Context = c
	return m
}


================================================
FILE: mail/mail_test.go
================================================
package mail

import (
	"html/template"
	"net/http"
	"testing"

	"github.com/gobuffalo/buffalo"
	"github.com/gobuffalo/buffalo/render"
	"github.com/gobuffalo/httptest"
	"github.com/stretchr/testify/require"
)

func Test_NewFromData(t *testing.T) {
	r := require.New(t)
	m := NewFromData(map[string]any{
		"foo": "bar",
	})
	r.Equal("bar", m.Data["foo"])
}

func Test_New(t *testing.T) {
	r := require.New(t)

	var m Message
	app := buffalo.New(buffalo.Options{})
	app.GET("/", func(c buffalo.Context) error {
		c.Set("foo", "bar")
		m = New(c)
		return c.Render(http.StatusOK, render.String(""))
	})
	w := httptest.New(app)
	w.HTML("/").Get()

	r.NotNil(m)
	r.Equal("bar", m.Data["foo"])
	rp, ok := m.Data["rootPath"].(buffalo.RouteHelperFunc)
	r.True(ok)
	x, err := rp(map[string]any{})
	r.NoError(err)
	r.Equal(template.HTML("/"), x)
}


================================================
FILE: mail/message.go
================================================
package mail

import (
	"bytes"
	"context"
	"io"
	"maps"
	"sync"

	"github.com/gobuffalo/buffalo/render"
)

// Message represents an Email message
type Message struct {
	Context     context.Context
	From        string
	To          []string
	CC          []string
	Bcc         []string
	Subject     string
	Headers     map[string]string
	Data        render.Data
	Bodies      []Body
	Attachments []Attachment
	moot        *sync.RWMutex
}

func (m *Message) merge(data render.Data) render.Data {
	m.moot.Lock()
	d := maps.Clone(m.Data)
	m.moot.Unlock()
	maps.Copy(d, data)
	return d
}

// AddBody the message by receiving a renderer and rendering data, first message will be
// used as the main message Body rest of them will be passed as alternative bodies on the
// email message
func (m *Message) AddBody(r render.Renderer, data render.Data) error {
	buf := bytes.NewBuffer([]byte{})
	err := r.Render(buf, m.merge(data))

	if err != nil {
		return err
	}

	m.Bodies = append(m.Bodies, Body{
		Content:     buf.String(),
		ContentType: r.ContentType(),
	})

	return nil
}

// AddBodies Allows to add multiple bodies to the message, it returns errors that
// could happen in the rendering.
func (m *Message) AddBodies(data render.Data, renderers ...render.Renderer) error {
	for _, r := range renderers {
		err := m.AddBody(r, data)
		if err != nil {
			return err
		}
	}

	return nil
}

// AddAttachment adds the attachment to the list of attachments the Message has.
func (m *Message) AddAttachment(name, contentType string, r io.Reader) error {
	m.Attachments = append(m.Attachments, Attachment{
		Name:        name,
		ContentType: contentType,
		Reader:      r,
		Embedded:    false,
	})

	return nil
}

// AddEmbedded adds the attachment to the list of attachments
// the Message has and uses inline instead of attachement property.
func (m *Message) AddEmbedded(name string, r io.Reader) error {
	m.Attachments = append(m.Attachments, Attachment{
		Name:     name,
		Reader:   r,
		Embedded: true,
	})

	return nil
}

// SetHeader sets the heder field and value for the message
func (m *Message) SetHeader(field, value string) {
	m.Headers[field] = value
}


================================================
FILE: mail/sender.go
================================================
package mail

// Sender defines the interface for sending individual email messages.
type Sender interface {
	// Send delivers a single email message.
	Send(Message) error
}

// BatchSender defines the interface for sending multiple email messages.
type BatchSender interface {
	Sender
	// SendBatch delivers multiple messages. It returns per-message errors
	// and any general error that prevented sending entirely.
	SendBatch(messages ...Message) (errorsByMessages []error, generalError error)
}


================================================
FILE: mail/smtp_auth.go
================================================
// Portions of this code are derived from the go-mail/mail project.
// https://github.com/go-mail/mail (MIT License)

package mail

import (
	"bytes"
	"fmt"
	"net/smtp"
	"slices"
)

// loginAuth is an smtp.Auth that implements the LOGIN authentication mechanism.
type loginAuth struct {
	username string
	password string
	host     string
}

func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
	if !server.TLS {
		if !slices.Contains(server.Auth, "LOGIN") {
			return "", nil, fmt.Errorf("gomail: unencrypted connection")
		}
	}
	if server.Name != a.host {
		return "", nil, fmt.Errorf("gomail: wrong host name")
	}
	return "LOGIN", nil, nil
}

func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
	if !more {
		return nil, nil
	}

	switch {
	case bytes.Equal(fromServer, []byte("Username:")):
		return []byte(a.username), nil
	case bytes.Equal(fromServer, []byte("Password:")):
		return []byte(a.password), nil
	default:
		return nil, fmt.Errorf("gomail: unexpected server challenge: %s", fromServer)
	}
}


================================================
FILE: mail/smtp_errors.go
================================================
// Portions of this code are derived from the go-mail/mail project.
// https://github.com/go-mail/mail (MIT License)

package mail

import "fmt"

// sendError represents the failure to transmit a Message, detailing the cause
// of the failure and index of the Message within a batch.
type sendError struct {
	// Index specifies the index of the Message within a batch.
	Index uint
	Cause error
}

func (err *sendError) Error() string {
	return fmt.Sprintf("gomail: could not send email %d: %v",
		err.Index+1, err.Cause)
}


================================================
FILE: mail/smtp_message.go
================================================
// Portions of this code are derived from the go-mail/mail project.
// https://github.com/go-mail/mail (MIT License)

package mail

import (
	"bytes"
	"io"
	"os"
	"path/filepath"
	"time"
)

// smtpMessage represents an email for SMTP transmission.
type smtpMessage struct {
	header      smtpHeader
	parts       []*part
	attachments []*file
	embedded    []*file
	charset     string
	encoding    encoding
	hEncoder    mimeEncoder
	buf         bytes.Buffer
	boundary    string
}

type smtpHeader map[string][]string

type part struct {
	contentType string
	copier      func(io.Writer) error
	encoding    encoding
}

func newSMTPMessage(settings ...messageSetting) *smtpMessage {
	m := &smtpMessage{
		header:   make(smtpHeader),
		charset:  "UTF-8",
		encoding: encodingQuotedPrintable,
	}

	m.applySettings(settings)

	if m.encoding == encodingBase64 {
		m.hEncoder = bEncoding
	} else {
		m.hEncoder = qEncoding
	}

	return m
}

func (m *smtpMessage) applySettings(settings []messageSetting) {
	for _, s := range settings {
		s(m)
	}
}

type messageSetting func(m *smtpMessage)

type encoding string

const (
	encodingQuotedPrintable encoding = "quoted-printable"
	encodingBase64          encoding = "base64"
	encodingUnencoded       encoding = "8bit"
)

func (m *smtpMessage) setHeader(field string, value ...string) {
	m.encodeHeader(value)
	m.header[field] = value
}

func (m *smtpMessage) encodeHeader(values []string) {
	for i := range values {
		values[i] = m.encodeString(values[i])
	}
}

func (m *smtpMessage) encodeString(value string) string {
	return m.hEncoder.Encode(m.charset, value)
}

func (m *smtpMessage) setBody(contentType, body string, settings ...partSetting) {
	m.setBodyWriter(contentType, newCopier(body), settings...)
}

func (m *smtpMessage) setBodyWriter(contentType string, f func(io.Writer) error, settings ...partSetting) {
	m.parts = []*part{m.newPart(contentType, f, settings)}
}

func (m *smtpMessage) addAlternative(contentType, body string, settings ...partSetting) {
	m.addAlternativeWriter(contentType, newCopier(body), settings...)
}

func newCopier(s string) func(io.Writer) error {
	return func(w io.Writer) error {
		_, err := io.WriteString(w, s)
		return err
	}
}

func (m *smtpMessage) addAlternativeWriter(contentType string, f func(io.Writer) error, settings ...partSetting) {
	m.parts = append(m.parts, m.newPart(contentType, f, settings))
}

func (m *smtpMessage) newPart(contentType string, f func(io.Writer) error, settings []partSetting) *part {
	p := &part{
		contentType: contentType,
		copier:      f,
		encoding:    m.encoding,
	}

	for _, s := range settings {
		s(p)
	}

	return p
}

type partSetting func(*part)

func setPartEncoding(e encoding) partSetting {
	return partSetting(func(p *part) {
		p.encoding = e
	})
}

type file struct {
	Name     string
	Header   map[string][]string
	CopyFunc func(w io.Writer) error
}

func (f *file) setHeader(field, value string) {
	f.Header[field] = []string{value}
}

type fileSetting func(*file)

func setCopyFunc(f func(io.Writer) error) fileSetting {
	return func(fi *file) {
		fi.CopyFunc = f
	}
}

func (m *smtpMessage) attach(filename string, settings ...fileSetting) {
	m.attachments = m.appendFile(m.attachments, fileFromFilename(filename), settings)
}

func (m *smtpMessage) embed(filename string, settings ...fileSetting) {
	m.embedded = m.appendFile(m.embedded, fileFromFilename(filename), settings)
}

func fileFromFilename(name string) *file {
	return &file{
		Name:   filepath.Base(name),
		Header: make(map[string][]string),
		CopyFunc: func(w io.Writer) error {
			h, err := os.Open(name)
			if err != nil {
				return err
			}
			if _, err := io.Copy(w, h); err != nil {
				h.Close()
				return err
			}
			return h.Close()
		},
	}
}

func (m *smtpMessage) formatDate(date time.Time) string {
	return date.Format(time.RFC1123Z)
}

func (m *smtpMessage) appendFile(list []*file, f *file, settings []fileSetting) []*file {
	for _, s := range settings {
		s(f)
	}

	if list == nil {
		return []*file{f}
	}

	return append(list, f)
}


================================================
FILE: mail/smtp_mime.go
================================================
// Portions of this code are derived from the go-mail/mail project.
// https://github.com/go-mail/mail (MIT License)

package mail

import (
	"mime"
	"mime/quotedprintable"
	"strings"
)

var newQPWriter = quotedprintable.NewWriter

type mimeEncoder struct {
	mime.WordEncoder
}

var (
	bEncoding     = mimeEncoder{mime.BEncoding}
	qEncoding     = mimeEncoder{mime.QEncoding}
	lastIndexByte = strings.LastIndexByte
)


================================================
FILE: mail/smtp_send.go
================================================
// Portions of this code are derived from the go-mail/mail project.
// https://github.com/go-mail/mail (MIT License)

package mail

import (
	"fmt"
	stdmail "net/mail"
	"slices"
)

// sendSMTP sends emails using the given Sender.
func sendSMTP(s sender, msg ...*smtpMessage) []error {
	errors := make([]error, len(msg))
	for i, m := range msg {
		if err := sendSingle(s, m); err != nil {
			errors[i] = &sendError{Cause: err, Index: uint(i)}
		}
	}

	return errors
}

func sendSingle(s sender, m *smtpMessage) error {
	from, err := m.getFrom()
	if err != nil {
		return err
	}

	to, err := m.getRecipients()
	if err != nil {
		return err
	}

	if err := s.Send(from, to, m); err != nil {
		return err
	}

	return nil
}

func (m *smtpMessage) getFrom() (string, error) {
	from := m.header["Sender"]
	if len(from) == 0 {
		from = m.header["From"]
		if len(from) == 0 {
			return "", fmt.Errorf(`gomail: invalid message, "From" field is absent`)
		}
	}

	return parseAddress(from[0])
}

func (m *smtpMessage) getRecipients() ([]string, error) {
	n := 0
	for _, field := range []string{"To", "Cc", "Bcc"} {
		if addresses, ok := m.header[field]; ok {
			n += len(addresses)
		}
	}
	list := make([]string, 0, n)

	for _, field := range []string{"To", "Cc", "Bcc"} {
		if addresses, ok := m.header[field]; ok {
			for _, a := range addresses {
				addr, err := parseAddress(a)
				if err != nil {
					return nil, err
				}
				list = addAddress(list, addr)
			}
		}
	}

	return list, nil
}

func addAddress(list []string, addr string) []string {
	if slices.Contains(list, addr) {
		return list
	}
	return append(list, addr)
}

func parseAddress(field string) (string, error) {
	addr, err := stdmail.ParseAddress(field)
	if err != nil {
		return "", fmt.Errorf("gomail: invalid address %q: %v", field, err)
	}
	return addr.Address, nil
}


================================================
FILE: mail/smtp_sender.go
================================================
package mail

import (
	"fmt"
	"io"
	"strconv"
)

// SMTPSender delivers emails via an SMTP server.
type SMTPSender struct {
	// Dialer configures the connection to the SMTP server.
	Dialer *Dialer
}

// Send delivers a single message via SMTP.
func (sm SMTPSender) Send(message Message) error {
	return sm.Dialer.dialAndSend(sm.prepareMessage(message))
}

// SendBatch delivers multiple messages using a single SMTP connection.
// Returns per-message errors and any general connection error.
func (sm SMTPSender) SendBatch(messages ...Message) (errorsByMessages []error, generalError error) {
	preparedMessages := make([]*smtpMessage, len(messages))
	for i, message := range messages {
		preparedMessages[i] = sm.prepareMessage(message)
	}

	s, err := sm.Dialer.dial()
	if err != nil {
		return nil, err
	}
	defer s.Close()

	return sendSMTP(s, preparedMessages...), nil
}
func (sm SMTPSender) prepareMessage(message Message) *smtpMessage {
	gm := newSMTPMessage()

	gm.setHeader("From", message.From)
	gm.setHeader("To", message.To...)
	gm.setHeader("Subject", message.Subject)
	gm.setHeader("Cc", message.CC...)
	gm.setHeader("Bcc", message.Bcc...)

	sm.addBodies(message, gm)
	sm.addAttachments(message, gm)

	for field, value := range message.Headers {
		gm.setHeader(field, value)
	}

	return gm
}

func (sm SMTPSender) addBodies(message Message, gm *smtpMessage) {
	if len(message.Bodies) == 0 {
		return
	}

	mainBody := message.Bodies[0]
	gm.setBody(mainBody.ContentType, mainBody.Content, setPartEncoding(encodingUnencoded))

	for i := 1; i < len(message.Bodies); i++ {
		alt := message.Bodies[i]
		gm.addAlternative(alt.ContentType, alt.Content, setPartEncoding(encodingUnencoded))
	}
}

func (sm SMTPSender) addAttachments(message Message, gm *smtpMessage) {

	for _, at := range message.Attachments {
		currentAttachement := at
		settings := setCopyFunc(func(w io.Writer) error {
			_, err := io.Copy(w, currentAttachement.Reader)
			return err
		})

		if currentAttachement.Embedded {
			gm.embed(currentAttachement.Name, settings)
		} else {
			gm.attach(currentAttachement.Name, settings)
		}

	}
}

// NewSMTPSender builds a SMTP mail based in passed config.
func NewSMTPSender(host string, port string, user string, password string) (SMTPSender, error) {
	iport, err := strconv.Atoi(port)

	if err != nil {
		return SMTPSender{}, fmt.Errorf("invalid port for the SMTP mail")
	}

	dialer := &Dialer{
		Host: host,
		Port: iport,
	}

	if user != "" {
		dialer.Username = user
		dialer.Password = password
	}

	return SMTPSender{
		Dialer: dialer,
	}, nil
}


================================================
FILE: mail/smtp_sender_test.go
================================================
package mail_test

import (
	"bytes"
	"testing"

	"github.com/gobuffalo/buffalo/internal/fakesmtp"
	"github.com/gobuffalo/buffalo/mail"
	"github.com/gobuffalo/buffalo/render"
	"github.com/stretchr/testify/require"
)

var sender mail.Sender
var rend *render.Engine
var smtpServer *fakesmtp.Server

const smtpPort = "2002"

func init() {
	rend = render.New(render.Options{})
	smtpServer, _ = fakesmtp.New(smtpPort)
	sender, _ = mail.NewSMTPSender("127.0.0.1", smtpPort, "username", "password")

	go smtpServer.Start(smtpPort)
}

func TestSendPlain(t *testing.T) {
	smtpServer.Clear()
	r := require.New(t)

	m := mail.NewMessage()
	m.From = "mark@example.com"
	m.To = []string{"something@something.com"}
	m.Subject = "Cool Message"
	m.CC = []string{"other@other.com", "my@other.com"}
	m.Bcc = []string{"secret@other.com"}

	m.AddAttachment("someFile.txt", "text/plain", bytes.NewBuffer([]byte("hello")))
	m.AddAttachment("otherFile.txt", "text/plain", bytes.NewBuffer([]byte("bye")))
	m.AddEmbedded("test.jpg", bytes.NewBuffer([]byte("not a real image")))
	m.AddBody(rend.String("Hello <%= Name %>"), render.Data{"Name": "Antonio"})
	r.Equal(m.Bodies[0].Content, "Hello Antonio")

	m.SetHeader("X-SMTPAPI", `{"send_at": 1409348513}`)

	err := sender.Send(m)
	r.Nil(err)

	lastMessage := smtpServer.LastMessage()

	r.Contains(lastMessage, "FROM:<mark@example.com>")
	r.Contains(lastMessage, "RCPT TO:<other@other.com>")
	r.Contains(lastMessage, "RCPT TO:<my@other.com>")
	r.Contains(lastMessage, "RCPT TO:<secret@other.com>")
	r.Contains(lastMessage, "Subject: Cool Message")
	r.Contains(lastMessage, "Cc: other@other.com, my@other.com")
	r.Contains(lastMessage, "Content-Type: text/plain")
	r.Contains(lastMessage, "Hello Antonio")
	r.Contains(lastMessage, "Content-Disposition: attachment; filename=\"someFile.txt\"")
	r.Contains(lastMessage, "aGVsbG8=") //base64 of the file content
	r.Contains(lastMessage, "Content-Disposition: attachment; filename=\"otherFile.txt\"")
	r.Contains(lastMessage, "Ynll") //base64 of the file content
	r.Contains(lastMessage, "Content-Disposition: inline; filename=\"test.jpg\"")
	r.Contains(lastMessage, "bm90IGEgcmVhbCBpbWFnZQ==") //base64 of the file content

	r.Contains(lastMessage, `X-SMTPAPI: {"send_at": 1409348513}`)
}


================================================
FILE: mail/smtp_writeto.go
================================================
// Portions of this code are derived from the go-mail/mail project.
// https://github.com/go-mail/mail (MIT License)

package mail

import (
	"encoding/base64"
	"fmt"
	"io"
	"mime"
	"mime/multipart"
	"path/filepath"
	"strings"
	"time"
)

func (m *smtpMessage) WriteTo(w io.Writer) (int64, error) {
	mw := &messageWriter{w: w}
	mw.writeMessage(m)
	return mw.n, mw.err
}

func (w *messageWriter) writeMessage(m *smtpMessage) {
	if _, ok := m.header["MIME-Version"]; !ok {
		w.writeString("MIME-Version: 1.0\r\n")
	}
	if _, ok := m.header["Date"]; !ok {
		w.writeHeader("Date", m.formatDate(now()))
	}
	w.writeHeaders(m.header)

	if m.hasMixedPart() {
		w.openMultipart("mixed", m.boundary)
	}

	if m.hasRelatedPart() {
		w.openMultipart("related", m.boundary)
	}

	if m.hasAlternativePart() {
		w.openMultipart("alternative", m.boundary)
	}
	for _, part := range m.parts {
		w.writePart(part, m.charset)
	}
	if m.hasAlternativePart() {
		w.closeMultipart()
	}

	w.addFiles(m.embedded, false)
	if m.hasRelatedPart() {
		w.closeMultipart()
	}

	w.addFiles(m.attachments, true)
	if m.hasMixedPart() {
		w.closeMultipart()
	}
}

func (m *smtpMessage) hasMixedPart() bool {
	return (len(m.parts) > 0 && len(m.attachments) > 0) || len(m.attachments) > 1
}

func (m *smtpMessage) hasRelatedPart() bool {
	return (len(m.parts) > 0 && len(m.embedded) > 0) || len(m.embedded) > 1
}

func (m *smtpMessage) hasAlternativePart() bool {
	return len(m.parts) > 1
}

type messageWriter struct {
	w          io.Writer
	n          int64
	writers    [3]*multipart.Writer
	partWriter io.Writer
	depth      uint8
	err        error
}

func (w *messageWriter) openMultipart(mimeType, boundary string) {
	mw := multipart.NewWriter(w)
	if boundary != "" {
		mw.SetBoundary(boundary)
	}
	contentType := "multipart/" + mimeType + ";\r\n boundary=" + mw.Boundary()
	w.writers[w.depth] = mw

	if w.depth == 0 {
		w.writeHeader("Content-Type", contentType)
		w.writeString("\r\n")
	} else {
		w.createPart(map[string][]string{
			"Content-Type": {contentType},
		})
	}
	w.depth++
}

func (w *messageWriter) createPart(h map[string][]string) {
	w.partWriter, w.err = w.writers[w.depth-1].CreatePart(h)
}

func (w *messageWriter) closeMultipart() {
	if w.depth > 0 {
		w.writers[w.depth-1].Close()
		w.depth--
	}
}

func (w *messageWriter) writePart(p *part, charset string) {
	w.writeHeaders(map[string][]string{
		"Content-Type":              {p.contentType + "; charset=" + charset},
		"Content-Transfer-Encoding": {string(p.encoding)},
	})
	w.writeBody(p.copier, p.encoding)
}

func (w *messageWriter) addFiles(files []*file, isAttachment bool) {
	for _, f := range files {
		if _, ok := f.Header["Content-Type"]; !ok {
			mediaType := mime.TypeByExtension(filepath.Ext(f.Name))
			if mediaType == "" {
				mediaType = "application/octet-stream"
			}
			f.setHeader("Content-Type", mediaType+`; name="`+f.Name+`"`)
		}

		if _, ok := f.Header["Content-Transfer-Encoding"]; !ok {
			f.setHeader("Content-Transfer-Encoding", string(encodingBase64))
		}

		if _, ok := f.Header["Content-Disposition"]; !ok {
			var disp string
			if isAttachment {
				disp = "attachment"
			} else {
				disp = "inline"
			}
			f.setHeader("Content-Disposition", disp+`; filename="`+f.Name+`"`)
		}

		if !isAttachment {
			if _, ok := f.Header["Content-ID"]; !ok {
				f.setHeader("Content-ID", "<"+f.Name+">")
			}
		}
		w.writeHeaders(f.Header)
		w.writeBody(f.CopyFunc, encodingBase64)
	}
}

func (w *messageWriter) Write(p []byte) (int, error) {
	if w.err != nil {
		return 0, fmt.Errorf("gomail: cannot write as writer is in error")
	}

	var n int
	n, w.err = w.w.Write(p)
	w.n += int64(n)
	return n, w.err
}

func (w *messageWriter) writeString(s string) {
	if w.err != nil {
		return
	}
	var n int
	n, w.err = io.WriteString(w.w, s)
	w.n += int64(n)
}

func (w *messageWriter) writeHeader(k string, v ...string) {
	w.writeString(k)
	if len(v) == 0 {
		w.writeString(":\r\n")
		return
	}
	w.writeString(": ")

	charsLeft := 76 - len(k) - len(": ")

	for i, s := range v {
		if charsLeft < 1 {
			if i == 0 {
				w.writeString("\r\n ")
			} else {
				w.writeString(",\r\n ")
			}
			charsLeft = 75
		} else if i != 0 {
			w.writeString(", ")
			charsLeft -= 2
		}

		for len(s) > charsLeft {
			s = w.writeLine(s, charsLeft)
			charsLeft = 75
		}
		w.writeString(s)
		if i := lastIndexByte(s, '\n'); i != -1 {
			charsLeft = 75 - (len(s) - i - 1)
		} else {
			charsLeft -= len(s)
		}
	}
	w.writeString("\r\n")
}

func (w *messageWriter) writeLine(s string, charsLeft int) string {
	if i := strings.IndexByte(s, '\n'); i != -1 && i < charsLeft {
		w.writeString(s[:i+1])
		return s[i+1:]
	}

	for i := charsLeft - 1; i >= 0; i-- {
		if s[i] == ' ' {
			w.writeString(s[:i])
			w.writeString("\r\n ")
			return s[i+1:]
		}
	}

	for i := 75; i < len(s); i++ {
		if s[i] == ' ' {
			w.writeString(s[:i])
			w.writeString("\r\n ")
			return s[i+1:]
		}
		if s[i] == '\n' {
			w.writeString(s[:i+1])
			return s[i+1:]
		}
	}

	w.writeString(s)
	return ""
}

func (w *messageWriter) writeHeaders(h map[string][]string) {
	if w.depth == 0 {
		for k, v := range h {
			if k != "Bcc" {
				w.writeHeader(k, v...)
			}
		}
	} else {
		w.createPart(h)
	}
}

func (w *messageWriter) writeBody(f func(io.Writer) error, enc encoding) {
	var subWriter io.Writer
	if w.depth == 0 {
		w.writeString("\r\n")
		subWriter = w.w
	} else {
		subWriter = w.partWriter
	}

	if enc == encodingBase64 {
		wc := base64.NewEncoder(base64.StdEncoding, newBase64LineWriter(subWriter))
		w.err = f(wc)
		wc.Close()
	} else if enc == encodingUnencoded {
		w.err = f(subWriter)
	} else {
		wc := newQPWriter(subWriter)
		w.err = f(wc)
		wc.Close()
	}
}

const maxLineLen = 76

type base64LineWriter struct {
	w       io.Writer
	lineLen int
}

func newBase64LineWriter(w io.Writer) *base64LineWriter {
	return &base64LineWriter{w: w}
}

func (w *base64LineWriter) Write(p []byte) (int, error) {
	n := 0
	for len(p)+w.lineLen > maxLineLen {
		w.w.Write(p[:maxLineLen-w.lineLen])
		w.w.Write([]byte("\r\n"))
		p = p[maxLineLen-w.lineLen:]
		n += maxLineLen - w.lineLen
		w.lineLen = 0
	}

	w.w.Write(p)
	w.lineLen += len(p)

	return n + len(p), nil
}

var now = time.Now


================================================
FILE: method_override.go
================================================
package buffalo

import (
	"net/http"

	"github.com/gobuffalo/buffalo/internal/defaults"
)

// MethodOverride is the default implementation for the
// Options#MethodOverride. By default it will look for a form value
// name `_method` and change the request method if that is
// present and the original request is of type "POST". This is
// added automatically when using `New` Buffalo, unless
// an alternative is defined in the Options.
func MethodOverride(res http.ResponseWriter, req *http.Request) {
	if req.Method == "POST" {
		req.Method = defaults.String(req.FormValue("_method"), "POST")
		req.Form.Del("_method")
		req.PostForm.Del("_method")
	}
}


================================================
FILE: method_override_test.go
================================================
package buffalo

import (
	"net/http"
	"net/url"
	"testing"

	"github.com/gobuffalo/buffalo/render"
	"github.com/gobuffalo/httptest"
	"github.com/stretchr/testify/require"
)

func Test_MethodOverride(t *testing.T) {
	r := require.New(t)

	a := New(Options{})
	a.PUT("/", func(c Context) error {
		return c.Render(http.StatusOK, render.String("you put me!"))
	})

	w := httptest.New(a)
	res := w.HTML("/").Post(url.Values{"_method": []string{"PUT"}})
	r.Equal(http.StatusOK, res.Code)
	r.Equal("you put me!", res.Body.String())
}


================================================
FILE: middleware.go
================================================
package buffalo

import (
	"maps"
	"net/http"
	"reflect"
	"runtime"
	"strings"
	"sync"
)

// MiddlewareFunc defines the interface for a piece of Buffalo
// Middleware.
/*
	func DoSomething(next Handler) Handler {
		return func(c Context) error {
			// do something before calling the next handler
			err := next(c)
			// do something after call the handler
			return err
		}
	}
*/
type MiddlewareFunc func(Handler) Handler

const funcKeyDelimeter = ":"

// Use the specified Middleware for the App.
// When defined on an `*App` the specified middleware will be
// inherited by any `Group` calls that are made on that on
// the App.
func (a *App) Use(mw ...MiddlewareFunc) {
	a.Middleware.Use(mw...)
}

// MiddlewareStack manages the middleware stack for an App/Group.
type MiddlewareStack struct {
	stack []MiddlewareFunc
	skips map[string]bool
}

func (ms MiddlewareStack) String() string {
	s := []string{}
	for _, m := range ms.stack {
		s = append(s, funcKey(m))
	}

	return strings.Join(s, "\n")
}

func (ms *MiddlewareStack) clone() *MiddlewareStack {
	n := newMiddlewareStack()
	n.stack = append(n.stack, ms.stack...)
	maps.Copy(n.skips, ms.skips)
	return n
}

// Clear wipes out the current middleware stack for the App/Group,
// any middleware previously defined will be removed leaving an empty
// middleware stack.
func (ms *MiddlewareStack) Clear() {
	ms.stack = []MiddlewareFunc{}
	ms.skips = map[string]bool{}
}

// Use the specified Middleware for the App.
// When defined on an `*App` the specified middleware will be
// inherited by any `Group` calls that are made on that on
// the App.
func (ms *MiddlewareStack) Use(mw ...MiddlewareFunc) {
	ms.stack = append(ms.stack, mw...)
}

// Remove the specified Middleware(s) for the App/group. This is useful when
// the middleware will be skipped by the entire group.
/*
	a.Middleware.Remove(Authorization)
*/
func (ms *MiddlewareStack) Remove(mws ...MiddlewareFunc) {
	result := []MiddlewareFunc{}

base:
	for _, existing := range ms.stack {
		for _, banned := range mws {
			if funcKey(existing) == funcKey(banned) {
				continue base
			}
		}

		result = append(result, existing)
	}

	ms.stack = result

}

// Skip a specified piece of middleware the specified Handlers.
// This is useful for things like wrapping your application in an
// authorization middleware, but skipping it for things the home
// page, the login page, etc...
/*
	a.Middleware.Skip(Authorization, HomeHandler, LoginHandler, RegistrationHandler)
*/
func (ms *MiddlewareStack) Skip(mw MiddlewareFunc, handlers ...Handler) {
	for _, h := range handlers {
		key := funcKey(mw, h)
		ms.skips[key] = true
	}
}

// Replace a piece of middleware with another piece of middleware. Great for
// testing.
func (ms *MiddlewareStack) Replace(mw1 MiddlewareFunc, mw2 MiddlewareFunc) {
	m1k := funcKey(mw1)
	stack := []MiddlewareFunc{}
	for _, mw := range ms.stack {
		if funcKey(mw) == m1k {
			stack = append(stack, mw2)
		} else {
			stack = append(stack, mw)
		}
	}
	ms.stack = stack
}

// assertMiddleware is a hidden middleware that works just befor and after the
// actual handler runs to make it sure everything is OK with the Handler
// specification.
//
// It writes response header with `http.StatusOK` if the request handler exited
// without error but the response status is still zero. Setting response is the
// responsibility of handler but this middleware make it sure the response
// should be compatible with middleware specification.
//
// See also: https://github.com/gobuffalo/buffalo/issues/2339
func assertMiddleware(handler Handler) Handler {
	return func(c Context) error {
		err := handler(c)
		if err != nil {
			return err
		}

		if res, ok := c.Response().(*Response); ok {
			if res.Status == 0 {
				res.WriteHeader(http.StatusOK)
				c.Logger().Debug("warning: handler exited without setting the response status. 200 OK will be used.")
			}
		}

		return err
	}
}

func (ms *MiddlewareStack) handler(info RouteInfo) Handler {
	tstack := []MiddlewareFunc{assertMiddleware}

	if len(ms.stack) > 0 {
		sl := len(ms.stack) - 1
		for i := sl; i >= 0; i-- {
			mw := ms.stack[i]
			key := funcKey(mw, info)
			if !ms.skips[key] {
				tstack = append(tstack, mw)
			}
		}
	}

	h := info.Handler
	for _, mw := range tstack {
		h = mw(h)
	}

	return h
}

func newMiddlewareStack(mws ...MiddlewareFunc) *MiddlewareStack {
	return &MiddlewareStack{
		stack: mws,
		skips: map[string]bool{},
	}
}

func funcKey(funcs ...any) string {
	names := []string{}
	for _, f := range funcs {
		if n, ok := f.(RouteInfo); ok {
			names = append(names, n.HandlerName)
			continue
		}
		rv := reflect.ValueOf(f)
		ptr := rv.Pointer()
		keyMapMutex.Lock()
		if n, ok := keyMap[ptr]; ok {
			keyMapMutex.Unlock()
			names = append(names, n)
			continue
		}
		keyMapMutex.Unlock()
		n := ptrName(ptr)
		keyMapMutex.Lock()
		keyMap[ptr] = n
		keyMapMutex.Unlock()
		names = append(names, n)
	}
	return strings.Join(names, funcKeyDelimeter)
}

func ptrName(ptr uintptr) string {
	fnc := runtime.FuncForPC(ptr)
	n := fnc.Name()

	n = strings.Replace(n, "-fm", "", 1)
	n = strings.Replace(n, "(", "", 1)
	n = strings.Replace(n, ")", "", 1)
	return n
}

func setFuncKey(f any, name string) {
	rv := reflect.ValueOf(f)
	if rv.Kind() == reflect.Ptr {
		rv = rv.Elem()
	}
	ptr := rv.Pointer()
	keyMapMutex.Lock()
	keyMap[ptr] = name
	keyMapMutex.Unlock()
}

var keyMap = map[uintptr]string{}
var keyMapMutex = sync.Mutex{}


================================================
FILE: middleware_test.go
================================================
package buffalo

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/gobuffalo/buffalo/render"
	"github.com/gobuffalo/httptest"
	"github.com/stretchr/testify/require"
)

// Test_App_Use tests that middleware gets added
func Test_App_Use(t *testing.T) {
	r := require.New(t)

	log := []string{}
	a := New(Options{})
	a.Use(func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "start")
			err := h(c)
			log = append(log, "end")
			return err
		}
	})

	a.GET("/", func(c Context) error {
		log = append(log, "handler")
		return nil
	})

	w := httptest.New(a)
	w.HTML("/").Get()
	r.Len(log, 3)
	r.Equal([]string{"start", "handler", "end"}, log)
}

// Test_Middleware_Replace tests that middleware gets added
func Test_Middleware_Replace(t *testing.T) {
	r := require.New(t)

	log := []string{}
	a := New(Options{})
	mw1 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "m1 start")
			err := h(c)
			log = append(log, "m1 end")
			return err
		}
	}
	mw2 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "m2 start")
			err := h(c)
			log = append(log, "m2 end")
			return err
		}
	}
	a.Use(mw1)
	a.Middleware.Replace(mw1, mw2)

	a.GET("/", func(c Context) error {
		log = append(log, "handler")
		return nil
	})

	w := httptest.New(a)
	w.HTML("/").Get()
	r.Len(log, 3)
	r.Equal([]string{"m2 start", "handler", "m2 end"}, log)
}

// Test_Middleware_Skip tests that middleware gets skipped
func Test_Middleware_Skip(t *testing.T) {
	r := require.New(t)

	log := []string{}
	a := New(Options{})
	mw1 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "mw1 start")
			err := h(c)
			log = append(log, "mw1 end")
			return err
		}
	}
	mw2 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "mw2 start")
			err := h(c)
			log = append(log, "mw2 end")
			return err
		}
	}
	a.Use(mw1)
	a.Use(mw2)

	h1 := func(c Context) error {
		log = append(log, "h1")
		return nil
	}
	h2 := func(c Context) error {
		log = append(log, "h2")
		return nil
	}

	a.GET("/h1", h1)
	a.GET("/h2", h2)

	a.Middleware.Skip(mw2, h2)

	w := httptest.New(a)

	w.HTML("/h2").Get()
	r.Len(log, 3)
	r.Equal([]string{"mw1 start", "h2", "mw1 end"}, log)

	log = []string{}
	w.HTML("/h1").Get()
	r.Len(log, 5)
	r.Equal([]string{"mw1 start", "mw2 start", "h1", "mw2 end", "mw1 end"}, log)
}

type carsResource struct {
	Resource
}

func (ur *carsResource) Show(c Context) error {
	return c.Render(http.StatusOK, render.String("show"))
}

func (ur *carsResource) List(c Context) error {
	return c.Render(http.StatusOK, render.String("list"))
}

// Test_Middleware_Skip tests that middleware gets skipped
func Test_Middleware_Skip_Resource(t *testing.T) {
	r := require.New(t)

	log := []string{}
	mw1 := func(h Handler) Handler {
		return func(c Context) error {
			log = append(log, "mw1 start")
			err := h(c)
			log = append(log, "mw1 end")
			return err
		}
	}

	a := New(Options{})
	var cr Resource = &carsResource{}
	g := a.Resource("/autos", cr)
	g.Use(mw1)

	var ur Resource = &carsResource{}
	g = a.Resource("/cars", ur)
	g.Use(mw1)

	// fmt.Println("set up skip")
	g.Middleware.Skip(mw1, ur.Show)

	w := httptest.New(a)

	// fmt.Println("make autos call")
	log = []string{}
	res := w.HTML("/autos/1").Get()
	r.Len(log, 2)
	r.Equal("show", res.Body.String())

	// fmt.Println("make list call")
	log = []string{}
	res = w.HTML("/cars").Get()
	r.Len(log, 2)
	r.Equal([]string{"mw1 start", "mw1 end"}, log)
	r.Equal("list", res.Body.String())

	// fmt.Println("make show call")
	log = []string{}
	res = w.HTML("/cars/1").Get()
	r.Len(log, 0)
	r.Equal("show", res.Body.String())

}

// Test_Middleware_Clear confirms that middle gets cleared
func Test_Middleware_Clear(t *testing.T) {
	r := require.New(t)
	mws := newMiddlewareStack()
	mw := func(h Handler) Handler { return h }
	mws.Use(mw)
	mws.Skip(mw, voidHandler)

	r.Len(mws.stack, 1)
	r.Len(mws.skips, 1)

	mws.Clear()

	r.Len(mws.stack, 0)
	r.Len(mws.skips, 0)
}

func Test_Middleware_Remove(t *testing.T) {
	r := require.New(t)
	log := []string{}

	mw1 := func(h Handler) Handler {
		log = append(log, "mw1")
		return h
	}

	mw2 := func(h Handler) Handler {
		log = append(log, "mw2")
		return h
	}

	a := New(Options{})
	a.Use(mw2)
	a.Use(mw1)

	var cr Resource = &carsResource{}
	g := a.Resource("/autos", cr)
	g.Middleware.Remove(mw2)

	a.Resource("/all_log_autos", cr)
	w := httptest.New(a)

	ng := a.Resource("/no_log_autos", cr)
	ng.Middleware.Remove(mw1, mw2)

	_ = w.HTML("/autos/1").Get()
	r.Len(log, 1)
	r.Equal("mw1", log[0])

	log = []string{}
	_ = w.HTML("/all_log_autos/1").Get()
	r.Len(log, 2)
	r.Contains(log, "mw2")
	r.Contains(log, "mw1")

	log = []string{}
	_ = w.HTML("/no_log_autos/1").Get()
	r.Len(log, 0)
}

func Test_AssertMiddleware_NilStatus200(t *testing.T) {
	r := require.New(t)
	var status int

	a := New(Options{})
	a.Use(func(h Handler) Handler {
		return func(c Context) error {
			err := h(c)

			res, ok := c.Response().(*Response)
			r.True(ok)
			status = res.Status

			return err
		}
	})

	a.GET("/200", func(c Context) error {
		c.Response().WriteHeader(http.StatusOK) // explicitly set
		return nil
	})

	a.GET("/404", func(c Context) error {
		c.Response().WriteHeader(http.StatusNotFound) //explicitly set
		return nil
	})

	a.GET("/nil", func(c Context) error {
		return nil // return nil without setting response status. should be OK
	})

	a.GET("/500", func(c Context) error {
		return fmt.Errorf("error") // return error
	})

	a.GET("/502", func(c Context) error {
		return HTTPError{Status: http.StatusBadGateway} // return HTTPError
	})

	a.GET("/panic", func(c Context) error {
		panic("hoy hoy")
	})

	tests := []struct {
		path   string
		code   int
		status int
	}{
		{"/200", http.StatusOK, http.StatusOK}, // when the handler set response code explicitly (e.g. 200, 404)
		{"/404", http.StatusNotFound, http.StatusNotFound},
		{"/nil", http.StatusOK, http.StatusOK},        // when the handler returns nil without setting status code
		{"/502", http.StatusBadGateway, 0},            // set by defaultErrorHandler, when the handler just returns error
		{"/500", http.StatusInternalServerError, 0},   // set by defaultErrorHandler, when the handler returns HTTPError
		{"/panic", http.StatusInternalServerError, 0}, // set by PanicHandler
	}
	w := httptest.New(a)

	for _, tc := range tests {
		res := w.HTML("%s", tc.path).Get()
		r.Equal(tc.status, status)
		r.Equal(tc.code, res.Code)
	}
}


================================================
FILE: not_found_test.go
================================================
package buffalo

import (
	"encoding/json"
	"net/http"
	"testing"

	"github.com/gobuffalo/httptest"
	"github.com/stretchr/testify/require"
)

func Test_App_Dev_NotFound(t *testing.T) {
	r := require.New(t)

	a := New(Options{})
	a.Env = "development"
	a.GET("/foo", func(c Context) error { return nil })

	w := httptest.New(a)
	res := w.HTML("/bad").Get()

	body := res.Body.String()
	r.Contains(body, "404 - ERROR!")
	r.Contains(body, "/foo")
	r.Equal(http.StatusNotFound, res.Code)
}

func Test_App_Dev_NotFound_JSON(t *testing.T) {
	r := require.New(t)

	a := New(Options{})
	a.Env = "development"
	a.GET("/foo", func(c Context) error { return nil })

	w := httptest.New(a)
	res := w.JSON("/bad").Get()
	r.Equal(http.StatusNotFound, res.Code)

	jb := map[string]any{}
	err := json.NewDecoder(res.Body).Decode(&jb)
	r.NoError(err)
	r.Equal(float64(http.StatusNotFound), jb["code"])
}

func Test_App_Override_NotFound(t *testing.T) {
	r := require.New(t)

	a := New(Options{})
	a.ErrorHandlers[http.StatusNotFound] = func(status int, err error, c Context) error {
		c.Response().WriteHeader(http.StatusNotFound)
		c.Response().Write([]byte("oops!!!"))
		return nil
	}
	a.GET("/foo", func(c Context) error { return nil })

	w := httptest.New(a)
	res := w.HTML("/bad").Get()
	r.Equal(http.StatusNotFound, res.Code)

	body := res.Body.String()
	r.Equal(body, "oops!!!")
	r.NotContains(body, "/foo")
}


================================================
FILE: options.go
================================================
package buffalo

import (
	"context"
	"fmt"
	"net/http"
	"strings"

	"github.com/gobuffalo/buffalo/internal/defaults"
	"github.com/gobuffalo/buffalo/internal/env"
	"github.com/gobuffalo/buffalo/worker"
	"github.com/gobuffalo/logger"
	"github.com/gorilla/sessions"
)

// Options are used to configure and define how your application should run.
type Options struct {
	Name string `json:"name"`
	// Addr is the bind address provided to http.Server. Default is "127.0.0.1:3000"
	// Can be set using ENV vars "ADDR" and "PORT".
	Addr string `json:"addr"`
	// Host that this application will be available at. Default is "http://127.0.0.1:[$PORT|3000]".
	Host string `json:"host"`

	// Env is the "environment" in which the App is running. Default is "development".
	Env string `json:"env"`

	// LogLvl defaults to logger.DebugLvl.
	LogLvl logger.Level `json:"log_lvl"`
	// Logger to be used with the application. A default one is provided.
	Logger Logger `json:"-"`

	// MethodOverride allows for changing of the request method type. See the default
	// implementation at buffalo.MethodOverride
	MethodOverride http.HandlerFunc `json:"-"`

	// SessionStore is the `github.com/gorilla/sessions` store used to back
	// the session. It defaults to use a cookie store and the ENV variable
	// `SESSION_SECRET`.
	SessionStore sessions.Store `json:"-"`
	// SessionName is the name of the session cookie that is set. This defaults
	// to "_buffalo_session".
	SessionName string `json:"session_name"`

	// Timeout in second for ongoing requests when shutdown the server.
	// The default value is 60.
	TimeoutSecondShutdown int `json:"timeout_second_shutdown"`

	// Worker implements the Worker interface and can process tasks in the background.
	// Default is "github.com/gobuffalo/worker.Simple.
	Worker worker.Worker `json:"-"`
	// WorkerOff tells App.Start() whether to start the Worker process or not. Default is "false".
	WorkerOff bool `json:"worker_off"`

	// PreHandlers are http.Handlers that are called between the http.Server
	// and the buffalo Application.
	PreHandlers []http.Handler `json:"-"`
	// PreWare takes an http.Handler and returns an http.Handler
	// and acts as a pseudo-middleware between the http.Server and
	// a Buffalo application.
	PreWares []PreWare `json:"-"`

	// CompressFiles enables gzip compression of static files served by ServeFiles using
	// gorilla's CompressHandler (https://godoc.org/github.com/gorilla/handlers#CompressHandler).
	// Default is "false".
	CompressFiles bool `json:"compress_files"`

	Prefix  string          `json:"prefix"`
	Context context.Context `json:"-"`

	cancel context.CancelFunc
}

// PreWare takes an http.Handler and returns an http.Handler
// and acts as a pseudo-middleware between the http.Server and
// a Buffalo application.
type PreWare func(http.Handler) http.Handler

// NewOptions returns a new Options instance with sensible defaults
func NewOptions() Options {
	return optionsWithDefaults(Options{})
}

func optionsWithDefaults(opts Options) Options {
	opts.Env = defaults.String(opts.Env, env.Get("GO_ENV", "development"))
	opts.Name = defaults.String(opts.Name, "/")
	addr := "0.0.0.0"
	if opts.Env == "development" {
		addr = "127.0.0.1"
	}
	envAddr := env.Get("ADDR", addr)

	if strings.HasPrefix(envAddr, "unix:") {
		// UNIX domain socket doesn't have a port
		opts.Addr = envAddr
	} else {
		// TCP case
		opts.Addr = defaults.String(opts.Addr, fmt.Sprintf("%s:%s", envAddr, env.Get("PORT", "3000")))
	}
	opts.Host = defaults.String(opts.Host, env.Get("HOST", fmt.Sprintf("http://127.0.0.1:%s", env.Get("PORT", "3000"))))

	if opts.PreWares == nil {
		opts.PreWares = []PreWare{}
	}
	if opts.PreHandlers == nil {
		opts.PreHandlers = []http.Handler{}
	}

	if opts.Context == nil {
		opts.Context = context.Background()
	}
	opts.Context, opts.cancel = context.WithCancel(opts.Context)

	if opts.Logger == nil {
		if lvl, err := env.MustGet("LOG_LEVEL"); err == nil {
			opts.LogLvl, err = logger.ParseLevel(lvl)
			if err != nil {
				opts.LogLvl = logger.DebugLevel
			}
		}

		if opts.LogLvl == 0 {
			opts.LogLvl = logger.DebugLevel
		}

		opts.Logger = logger.New(opts.LogLvl)
	}

	if opts.SessionStore == nil {
		secret := env.Get("SESSION_SECRET", "")

		if secret == "" && (opts.Env == "development" || opts.Env == "test") {
			secret = "buffalo-secret"
		}

		// In production a SESSION_SECRET must be set!
		if secret == "" {
			opts.Logger.Warn("Unless you set SESSION_SECRET env variable, your session storage is not protected!")
		}

		cookieStore := sessions.NewCookieStore([]byte(secret))

		//Cookie secure attributes, see: https://www.owasp.org/index.php/Testing_for_cookies_attributes_(OTG-SESS-002)
		cookieStore.Options.HttpOnly = true
		if opts.Env == "production" {
			cookieStore.Options.Secure = true
		}

		opts.SessionStore = cookieStore
	}
	opts.SessionName = defaults.String(opts.SessionName, "_buffalo_session")

	if opts.Worker == nil {
		w := worker.NewSimpleWithContext(opts.Context)
		w.Logger = opts.Logger
		opts.Worker = w
	}

	opts.TimeoutSecondShutdown = defaults.Int(opts.TimeoutSecondShutdown, 60)

	return opts
}


================================================
FILE: options_test.go
================================================
package buffalo

import (
	"net/http"
	"strings"
	"testing"

	"github.com/gobuffalo/buffalo/internal/env"
	"github.com/stretchr/testify/require"
)

func TestOptions_NewOptions(t *testing.T) {
	tests := []struct {
		name      string
		env       string
		secret    string
		expectErr string
	}{
		{name: "Development doesn't fail with no secret", env: "development", secret: "", expectErr: "securecookie:"},
		{name: "Development doesn't fail with secret set", env: "development", secret: "secrets", expectErr: "securecookie:"},
		{name: "Test doesn't fail with secret set", env: "test", secret: "", expectErr: "securecookie:"},
		{name: "Test doesn't fail with secret set", env: "test", secret: "secrets", expectErr: "securecookie:"},
		{name: "Production fails with no secret", env: "production", secret: "", expectErr: "securecookie:"},
		{name: "Production doesn't fail with secret set", env: "production", secret: "secrets", expectErr: "securecookie:"},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			r := require.New(t)
			env.Temp(func() {
				env.Set("GO_ENV", test.env)
				env.Set("SESSION_SECRET", test.secret)

				opts := NewOptions()

				req, _ := http.NewRequest("GET", "/", strings.NewReader(""))
				req.AddCookie(&http.Cookie{Name: "_buffalo_session"})

				_, err := opts.SessionStore.New(req, "_buffalo_session")

				r.Error(err)
				r.Contains(err.Error(), test.expectErr)
			})
		})
	}
}


================================================
FILE: plugins/cache.go
================================================
package plugins

import (
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"os/user"
	"path/filepath"
	"sync"

	"github.com/gobuffalo/buffalo/internal/env"
)

type cachedPlugin struct {
	Commands Commands `json:"commands"`
	CheckSum string   `json:"check_sum"`
}

type cachedPlugins map[string]cachedPlugin

// CachePath returns the path to the plugins cache
var CachePath = func() string {
	home := "."
	if usr, err := user.Current(); err == nil {
		home = usr.HomeDir
	}
	return filepath.Join(home, ".buffalo", "plugin.cache")
}()

var cacheMoot sync.RWMutex

var cacheOn = env.Get("BUFFALO_PLUGIN_CACHE", "on")

var cache = func() cachedPlugins {
	m := cachedPlugins{}
	if cacheOn != "on" {
		return m
	}
	f, err := os.Open(CachePath)
	if err != nil {
		return m
	}
	defer f.Close()
	if err := json.NewDecoder(f).Decode(&m
Download .txt
gitextract_pzjmh4ui/

├── .github/
│   ├── CODEOWNERS
│   ├── FUNDING.yml
│   └── workflows/
│       ├── standard-go-test.yml
│       └── standard-stale.yml
├── .gitignore
├── BACKERS.md
├── Dockerfile
├── Dockerfile.build
├── Dockerfile.slim.build
├── LICENSE.txt
├── README.md
├── SECURITY.md
├── SHOULDERS.md
├── app.go
├── app_test.go
├── binding/
│   ├── bindable.go
│   ├── bindable_test.go
│   ├── binding.go
│   ├── binding_test.go
│   ├── decoders/
│   │   ├── decoders.go
│   │   ├── null_time.go
│   │   ├── null_time_test.go
│   │   ├── parse_time.go
│   │   ├── time.go
│   │   └── time_test.go
│   ├── file.go
│   ├── file_request_type_binder.go
│   ├── file_test.go
│   ├── html_content_type_binder.go
│   ├── json_content_type_binder.go
│   ├── request_binder.go
│   ├── request_binder_test.go
│   ├── types.go
│   └── xml_request_type_binder.go
├── buffalo.go
├── context.go
├── cookies.go
├── cookies_test.go
├── default_context.go
├── default_context_test.go
├── errors.go
├── errors_test.go
├── events.go
├── flash.go
├── flash_test.go
├── fs.go
├── fs_test.go
├── go.mod
├── go.sum
├── handler.go
├── home.go
├── internal/
│   ├── defaults/
│   │   ├── defaults.go
│   │   └── defaults_test.go
│   ├── env/
│   │   └── env.go
│   ├── fakesmtp/
│   │   ├── connection.go
│   │   └── server.go
│   ├── httpx/
│   │   ├── content_type.go
│   │   └── content_type_test.go
│   ├── meta/
│   │   ├── meta.go
│   │   └── meta_test.go
│   ├── nulls/
│   │   └── nulls.go
│   ├── templates/
│   │   ├── error.dev.html
│   │   ├── error.prod.html
│   │   └── notfound.prod.html
│   └── testdata/
│       ├── disk/
│       │   ├── file.txt
│       │   ├── file2.txt
│       │   └── under/
│       │       └── sub/
│       │           └── subfile
│       ├── embedded/
│       │   ├── embed.go
│       │   ├── file.txt
│       │   └── under/
│       │       └── sub/
│       │           └── subfile
│       └── panic.txt
├── logger.go
├── mail/
│   ├── README.md
│   ├── attachment.go
│   ├── body.go
│   ├── dialer.go
│   ├── mail.go
│   ├── mail_test.go
│   ├── message.go
│   ├── sender.go
│   ├── smtp_auth.go
│   ├── smtp_errors.go
│   ├── smtp_message.go
│   ├── smtp_mime.go
│   ├── smtp_send.go
│   ├── smtp_sender.go
│   ├── smtp_sender_test.go
│   └── smtp_writeto.go
├── method_override.go
├── method_override_test.go
├── middleware.go
├── middleware_test.go
├── not_found_test.go
├── options.go
├── options_test.go
├── plugins/
│   ├── cache.go
│   ├── command.go
│   ├── decorate.go
│   ├── events.go
│   ├── log.go
│   ├── log_debug.go
│   ├── plugcmds/
│   │   ├── available.go
│   │   ├── available_test.go
│   │   ├── plug_map.go
│   │   └── plug_map_test.go
│   ├── plugdeps/
│   │   ├── command.go
│   │   ├── plugdeps.go
│   │   ├── plugdeps_test.go
│   │   ├── plugin.go
│   │   ├── plugin_test.go
│   │   ├── plugins.go
│   │   ├── plugins_test.go
│   │   └── pop.go
│   ├── plugins.go
│   └── plugins_test.go
├── plugins.go
├── render/
│   ├── auto.go
│   ├── auto_test.go
│   ├── download.go
│   ├── download_test.go
│   ├── func.go
│   ├── func_test.go
│   ├── helpers.go
│   ├── html.go
│   ├── html_test.go
│   ├── js.go
│   ├── js_test.go
│   ├── json.go
│   ├── json_test.go
│   ├── markdown_test.go
│   ├── options.go
│   ├── partials_test.go
│   ├── plain.go
│   ├── plain_test.go
│   ├── render.go
│   ├── render_test.go
│   ├── renderer.go
│   ├── sse.go
│   ├── string.go
│   ├── string_map.go
│   ├── string_map_test.go
│   ├── string_test.go
│   ├── template.go
│   ├── template_engine.go
│   ├── template_helpers.go
│   ├── template_helpers_test.go
│   ├── template_test.go
│   ├── xml.go
│   └── xml_test.go
├── request_data.go
├── request_data_test.go
├── request_logger.go
├── resource.go
├── response.go
├── response_test.go
├── route.go
├── route_info.go
├── route_info_test.go
├── route_mappings.go
├── route_mappings_test.go
├── routenamer.go
├── router_test.go
├── runtime/
│   └── build.go
├── server.go
├── server_test.go
├── servers/
│   ├── listener.go
│   ├── servers.go
│   ├── simple.go
│   └── tls.go
├── session.go
├── session_test.go
├── worker/
│   ├── job.go
│   ├── simple.go
│   ├── simple_test.go
│   └── worker.go
├── wrappers.go
└── wrappers_test.go
Download .txt
SYMBOL INDEX (849 symbols across 147 files)

FILE: app.go
  type App (line 15) | type App struct
    method Muxer (line 32) | func (a *App) Muxer() *mux.Router {
  function New (line 37) | func New(opts Options) *App {

FILE: app_test.go
  function voidHandler (line 3) | func voidHandler(c Context) error {

FILE: binding/bindable.go
  type Bindable (line 8) | type Bindable interface

FILE: binding/bindable_test.go
  type orbison (line 11) | type orbison struct
    method Bind (line 15) | func (o *orbison) Bind(req *http.Request) error {
  function Test_Bindable (line 20) | func Test_Bindable(t *testing.T) {

FILE: binding/binding.go
  function buildFormDecoder (line 38) | func buildFormDecoder() *formam.Decoder {
  function RegisterTimeFormats (line 52) | func RegisterTimeFormats(layouts ...string) {
  function RegisterCustomDecoder (line 58) | func RegisterCustomDecoder(fn CustomTypeDecoder, types []any, fields []a...
  function Register (line 65) | func Register(contentType string, fn Binder) {
  function Exec (line 74) | func Exec(req *http.Request, value any) error {

FILE: binding/binding_test.go
  type blogPost (line 11) | type blogPost struct
  function Test_Register (line 17) | func Test_Register(t *testing.T) {
  function Test_RegisterCustomDecoder (line 47) | func Test_RegisterCustomDecoder(t *testing.T) {

FILE: binding/decoders/decoders.go
  function RegisterTimeFormats (line 38) | func RegisterTimeFormats(layouts ...string) {

FILE: binding/decoders/null_time.go
  function NullTimeDecoderFn (line 6) | func NullTimeDecoderFn() func([]string) (any, error) {

FILE: binding/decoders/null_time_test.go
  function Test_NullTimeCustomDecoder_Decode (line 11) | func Test_NullTimeCustomDecoder_Decode(t *testing.T) {

FILE: binding/decoders/parse_time.go
  function parseTime (line 7) | func parseTime(vals []string) (time.Time, error) {

FILE: binding/decoders/time.go
  function TimeDecoderFn (line 4) | func TimeDecoderFn() func([]string) (any, error) {

FILE: binding/decoders/time_test.go
  function TestParseTimeErrorParsing (line 10) | func TestParseTimeErrorParsing(t *testing.T) {
  function TestParseTime (line 17) | func TestParseTime(t *testing.T) {
  function TestParseTimeConflicting (line 52) | func TestParseTimeConflicting(t *testing.T) {

FILE: binding/file.go
  type File (line 8) | type File struct
    method Valid (line 14) | func (f File) Valid() bool {
    method String (line 18) | func (f File) String() string {

FILE: binding/file_request_type_binder.go
  type FileRequestTypeBinder (line 11) | type FileRequestTypeBinder struct
    method ContentTypes (line 16) | func (ht FileRequestTypeBinder) ContentTypes() []string {
    method BinderFunc (line 23) | func (ht FileRequestTypeBinder) BinderFunc() Binder {

FILE: binding/file_test.go
  type WithFile (line 21) | type WithFile struct
  type NamedFileSlice (line 25) | type NamedFileSlice struct
  type NamedFile (line 29) | type NamedFile struct
  function App (line 33) | func App() *buffalo.App {
  function Test_File_Upload_On_Struct (line 72) | func Test_File_Upload_On_Struct(t *testing.T) {
  function Test_File_Upload_On_Struct_WithTag_WithMultipleFiles (line 85) | func Test_File_Upload_On_Struct_WithTag_WithMultipleFiles(t *testing.T) {
  function Test_File_Upload_On_Struct_WithTag (line 98) | func Test_File_Upload_On_Struct_WithTag(t *testing.T) {
  function Test_File_Upload_On_Context (line 111) | func Test_File_Upload_On_Context(t *testing.T) {
  function newFileUploadRequest (line 126) | func newFileUploadRequest(uri string, paramName string, paths ...string)...

FILE: binding/html_content_type_binder.go
  type HTMLContentTypeBinder (line 10) | type HTMLContentTypeBinder struct
    method ContentTypes (line 15) | func (ht HTMLContentTypeBinder) ContentTypes() []string {
    method BinderFunc (line 25) | func (ht HTMLContentTypeBinder) BinderFunc() Binder {

FILE: binding/json_content_type_binder.go
  type JSONContentTypeBinder (line 9) | type JSONContentTypeBinder struct
    method BinderFunc (line 12) | func (js JSONContentTypeBinder) BinderFunc() Binder {
    method ContentTypes (line 19) | func (js JSONContentTypeBinder) ContentTypes() []string {

FILE: binding/request_binder.go
  type RequestBinder (line 19) | type RequestBinder struct
    method Register (line 26) | func (rb *RequestBinder) Register(contentType string, fn Binder) {
    method Exec (line 35) | func (rb *RequestBinder) Exec(req *http.Request, value any) error {
  function NewRequestBinder (line 58) | func NewRequestBinder(requestBinders ...ContenTypeBinder) *RequestBinder {

FILE: binding/request_binder_test.go
  function Test_RequestBinder_Exec (line 12) | func Test_RequestBinder_Exec(t *testing.T) {
  function Test_RequestBinder_Exec_BlankContentType (line 30) | func Test_RequestBinder_Exec_BlankContentType(t *testing.T) {
  function Test_RequestBinder_Exec_Bindable (line 40) | func Test_RequestBinder_Exec_Bindable(t *testing.T) {
  function Test_RequestBinder_Exec_NoBinder (line 61) | func Test_RequestBinder_Exec_NoBinder(t *testing.T) {

FILE: binding/types.go
  type ContenTypeBinder (line 8) | type ContenTypeBinder interface
  type Binder (line 15) | type Binder
  type CustomTypeDecoder (line 18) | type CustomTypeDecoder

FILE: binding/xml_request_type_binder.go
  type XMLRequestTypeBinder (line 9) | type XMLRequestTypeBinder struct
    method BinderFunc (line 12) | func (xm XMLRequestTypeBinder) BinderFunc() Binder {
    method ContentTypes (line 19) | func (xm XMLRequestTypeBinder) ContentTypes() []string {

FILE: context.go
  type Context (line 18) | type Context interface
  type ParamValues (line 41) | type ParamValues interface
  method newContext (line 45) | func (a *App) newContext(info RouteInfo, res http.ResponseWriter, req *h...

FILE: cookies.go
  type Cookies (line 9) | type Cookies struct
    method Get (line 15) | func (c *Cookies) Get(name string) (string, error) {
    method Set (line 25) | func (c *Cookies) Set(name, value string, maxAge time.Duration) {
    method SetWithExpirationTime (line 38) | func (c *Cookies) SetWithExpirationTime(name, value string, expires ti...
    method SetWithPath (line 52) | func (c *Cookies) SetWithPath(name, value, path string) {
    method Delete (line 63) | func (c *Cookies) Delete(name string) {

FILE: cookies_test.go
  function TestCookies_Get (line 12) | func TestCookies_Get(t *testing.T) {
  function TestCookies_Set (line 31) | func TestCookies_Set(t *testing.T) {
  function TestCookies_SetWithPath (line 43) | func TestCookies_SetWithPath(t *testing.T) {
  function TestCookies_SetWithExpirationTime (line 55) | func TestCookies_SetWithExpirationTime(t *testing.T) {
  function TestCookies_Delete (line 68) | func TestCookies_Delete(t *testing.T) {

FILE: default_context.go
  type DefaultContext (line 31) | type DefaultContext struct
    method Response (line 44) | func (d *DefaultContext) Response() http.ResponseWriter {
    method Request (line 49) | func (d *DefaultContext) Request() *http.Request {
    method Params (line 55) | func (d *DefaultContext) Params() ParamValues {
    method Logger (line 60) | func (d *DefaultContext) Logger() Logger {
    method Param (line 66) | func (d *DefaultContext) Param(key string) string {
    method Set (line 72) | func (d *DefaultContext) Set(key string, value any) {
    method Value (line 82) | func (d *DefaultContext) Value(key any) any {
    method Session (line 98) | func (d *DefaultContext) Session() *Session {
    method Cookies (line 103) | func (d *DefaultContext) Cookies() *Cookies {
    method Flash (line 108) | func (d *DefaultContext) Flash() *Flash {
    method Render (line 121) | func (d *DefaultContext) Render(status int, rr render.Renderer) error {
    method Bind (line 179) | func (d *DefaultContext) Bind(value any) error {
    method LogField (line 186) | func (d *DefaultContext) LogField(key string, value any) {
    method LogFields (line 196) | func (d *DefaultContext) LogFields(values map[string]any) {
    method Error (line 203) | func (d *DefaultContext) Error(status int, err error) error {
    method Redirect (line 210) | func (d *DefaultContext) Redirect(status int, url string, args ...any)...
    method Data (line 250) | func (d *DefaultContext) Data() map[string]any {
    method String (line 262) | func (d *DefaultContext) String() string {
    method File (line 276) | func (d *DefaultContext) File(name string) (binding.File, error) {
    method MarshalJSON (line 290) | func (d *DefaultContext) MarshalJSON() ([]byte, error) {
  type paginable (line 112) | type paginable interface

FILE: default_context_test.go
  function basicContext (line 16) | func basicContext() DefaultContext {
  function Test_DefaultContext_Redirect (line 25) | func Test_DefaultContext_Redirect(t *testing.T) {
  function Test_DefaultContext_Redirect_Helper (line 38) | func Test_DefaultContext_Redirect_Helper(t *testing.T) {
  function Test_DefaultContext_Param (line 79) | func Test_DefaultContext_Param(t *testing.T) {
  function Test_DefaultContext_Param_form (line 90) | func Test_DefaultContext_Param_form(t *testing.T) {
  function Test_DefaultContext_Param_Multiple (line 109) | func Test_DefaultContext_Param_Multiple(t *testing.T) {
  function Test_DefaultContext_GetSet (line 135) | func Test_DefaultContext_GetSet(t *testing.T) {
  function Test_DefaultContext_Set_not_configured (line 145) | func Test_DefaultContext_Set_not_configured(t *testing.T) {
  function Test_DefaultContext_Value (line 154) | func Test_DefaultContext_Value(t *testing.T) {
  function Test_DefaultContext_Value_not_configured (line 164) | func Test_DefaultContext_Value_not_configured(t *testing.T) {
  function Test_DefaultContext_Render (line 170) | func Test_DefaultContext_Render(t *testing.T) {
  function Test_DefaultContext_Bind_Default (line 186) | func Test_DefaultContext_Bind_Default(t *testing.T) {
  function Test_DefaultContext_Bind_No_ContentType (line 210) | func Test_DefaultContext_Bind_No_ContentType(t *testing.T) {
  function Test_DefaultContext_Bind_Empty_ContentType (line 238) | func Test_DefaultContext_Bind_Empty_ContentType(t *testing.T) {
  function Test_DefaultContext_Bind_Default_BlankFields (line 267) | func Test_DefaultContext_Bind_Default_BlankFields(t *testing.T) {
  function Test_DefaultContext_Bind_JSON (line 293) | func Test_DefaultContext_Bind_JSON(t *testing.T) {
  function Test_DefaultContext_Data (line 318) | func Test_DefaultContext_Data(t *testing.T) {
  function Test_DefaultContext_Data_not_configured (line 325) | func Test_DefaultContext_Data_not_configured(t *testing.T) {
  function Test_DefaultContext_String (line 332) | func Test_DefaultContext_String(t *testing.T) {
  function Test_DefaultContext_String_EmptyData (line 341) | func Test_DefaultContext_String_EmptyData(t *testing.T) {
  function Test_DefaultContext_String_EmptyData_not_configured (line 347) | func Test_DefaultContext_String_EmptyData_not_configured(t *testing.T) {
  function Test_DefaultContext_MarshalJSON (line 354) | func Test_DefaultContext_MarshalJSON(t *testing.T) {
  function Test_DefaultContext_MarshalJSON_EmptyData (line 365) | func Test_DefaultContext_MarshalJSON_EmptyData(t *testing.T) {
  function Test_DefaultContext_MarshalJSON_EmptyData_not_configured (line 374) | func Test_DefaultContext_MarshalJSON_EmptyData_not_configured(t *testing...

FILE: errors.go
  type HTTPError (line 33) | type HTTPError struct
    method Unwrap (line 39) | func (h HTTPError) Unwrap() error {
    method Error (line 44) | func (h HTTPError) Error() string {
  type ErrorHandler (line 53) | type ErrorHandler
  type ErrorHandlers (line 65) | type ErrorHandlers
    method Get (line 70) | func (e ErrorHandlers) Get(status int) ErrorHandler {
    method Default (line 84) | func (e ErrorHandlers) Default(eh ErrorHandler) {
  method PanicHandler (line 92) | func (a *App) PanicHandler(next Handler) Handler {
  method defaultErrorMiddleware (line 123) | func (a *App) defaultErrorMiddleware(next Handler) Handler {
  function productionErrorResponseFor (line 174) | func productionErrorResponseFor(status int) []byte {
  type ErrorResponse (line 183) | type ErrorResponse struct
  constant defaultErrorCT (line 190) | defaultErrorCT = "text/html; charset=utf-8"
  function defaultErrorHandler (line 192) | func defaultErrorHandler(status int, origErr error, c Context) error {
  function errorResponseDefault (line 279) | func errorResponseDefault(defaultResponse, alternativeResponse *ErrorRes...
  type inspectHeaders (line 286) | type inspectHeaders
    method String (line 288) | func (i inspectHeaders) String() string {

FILE: errors_test.go
  type testLoggerHook (line 17) | type testLoggerHook struct
    method Fire (line 21) | func (lh *testLoggerHook) Fire(entry *logrus.Entry) error {
    method Levels (line 26) | func (lh *testLoggerHook) Levels() []logrus.Level {
  function Test_defaultErrorHandler_SetsContentType (line 32) | func Test_defaultErrorHandler_SetsContentType(t *testing.T) {
  function Test_defaultErrorHandler_Logger (line 46) | func Test_defaultErrorHandler_Logger(t *testing.T) {
  function Test_defaultErrorHandler_JSON_development (line 68) | func Test_defaultErrorHandler_JSON_development(t *testing.T) {
  function Test_defaultErrorHandler_XML_development (line 72) | func Test_defaultErrorHandler_XML_development(t *testing.T) {
  function Test_defaultErrorHandler_JSON_staging (line 76) | func Test_defaultErrorHandler_JSON_staging(t *testing.T) {
  function Test_defaultErrorHandler_XML_staging (line 80) | func Test_defaultErrorHandler_XML_staging(t *testing.T) {
  function Test_defaultErrorHandler_JSON_production (line 84) | func Test_defaultErrorHandler_JSON_production(t *testing.T) {
  function Test_defaultErrorHandler_XML_production (line 88) | func Test_defaultErrorHandler_XML_production(t *testing.T) {
  function testDefaultErrorHandler (line 92) | func testDefaultErrorHandler(t *testing.T, contentType, env string) {
  function Test_defaultErrorHandler_nil_error (line 139) | func Test_defaultErrorHandler_nil_error(t *testing.T) {
  function Test_PanicHandler (line 151) | func Test_PanicHandler(t *testing.T) {
  function Test_defaultErrorMiddleware (line 185) | func Test_defaultErrorMiddleware(t *testing.T) {
  function Test_SetErrorMiddleware (line 213) | func Test_SetErrorMiddleware(t *testing.T) {

FILE: events.go
  constant EvtAppStart (line 14) | EvtAppStart = "buffalo:app:start"
  constant EvtAppStartErr (line 16) | EvtAppStartErr = "buffalo:app:start:err"
  constant EvtAppStop (line 19) | EvtAppStop = "buffalo:app:stop"
  constant EvtAppStopErr (line 21) | EvtAppStopErr = "buffalo:app:stop:err"
  constant EvtRouteStarted (line 24) | EvtRouteStarted = "buffalo:route:started"
  constant EvtRouteFinished (line 26) | EvtRouteFinished = "buffalo:route:finished"
  constant EvtRouteErr (line 28) | EvtRouteErr = "buffalo:route:err"
  constant EvtServerStart (line 31) | EvtServerStart = "buffalo:server:start"
  constant EvtServerStartErr (line 33) | EvtServerStartErr = "buffalo:server:start:err"
  constant EvtServerStop (line 35) | EvtServerStop = "buffalo:server:stop"
  constant EvtServerStopErr (line 37) | EvtServerStopErr = "buffalo:server:stop:err"
  constant EvtWorkerStart (line 40) | EvtWorkerStart = "buffalo:worker:start"
  constant EvtWorkerStartErr (line 42) | EvtWorkerStartErr = "buffalo:worker:start:err"
  constant EvtWorkerStop (line 44) | EvtWorkerStop = "buffalo:worker:stop"
  constant EvtWorkerStopErr (line 46) | EvtWorkerStopErr = "buffalo:worker:stop:err"
  constant EvtFailureErr (line 49) | EvtFailureErr = "buffalo:failure:err"

FILE: flash.go
  constant flashKey (line 6) | flashKey = "_flash_"
  type Flash (line 9) | type Flash struct
    method Delete (line 14) | func (f Flash) Delete(key string) {
    method Clear (line 19) | func (f *Flash) Clear() {
    method Set (line 24) | func (f Flash) Set(key string, values []string) {
    method Add (line 29) | func (f Flash) Add(key, value string) {
    method persist (line 39) | func (f Flash) persist(session *Session) {
  function newFlash (line 45) | func newFlash(session *Session) *Flash {

FILE: flash_test.go
  function Test_FlashAdd (line 13) | func Test_FlashAdd(t *testing.T) {
  function Test_FlashRender (line 30) | func Test_FlashRender(t *testing.T) {
  function Test_FlashRenderEmpty (line 49) | func Test_FlashRenderEmpty(t *testing.T) {
  constant errorsTPL (line 64) | errorsTPL = `
  function Test_FlashRenderEntireFlash (line 71) | func Test_FlashRenderEntireFlash(t *testing.T) {
  constant keyTPL (line 86) | keyTPL = `<%= for (k, v) in flash { %>
  function Test_FlashRenderCustomKey (line 92) | func Test_FlashRenderCustomKey(t *testing.T) {
  function Test_FlashRenderCustomKeyNotDefined (line 107) | func Test_FlashRenderCustomKeyNotDefined(t *testing.T) {
  constant customKeyTPL (line 121) | customKeyTPL = `
  function Test_FlashNotClearedOnRedirect (line 127) | func Test_FlashNotClearedOnRedirect(t *testing.T) {

FILE: fs.go
  type FS (line 15) | type FS struct
    method Open (line 38) | func (f FS) Open(name string) (fs.File, error) {
    method getFile (line 56) | func (f FS) getFile(name string) (fs.File, error) {
  function NewFS (line 22) | func NewFS(embed fs.ReadDirFS, dir string) FS {
  type rootFile (line 66) | type rootFile struct
    method ReadDir (line 71) | func (f rootFile) ReadDir(n int) (entries []fs.DirEntry, err error) {
  function hideEmbedFile (line 82) | func hideEmbedFile(entries []fs.DirEntry) []fs.DirEntry {

FILE: fs_test.go
  function Test_FS_Disallows_Parent_Folders (line 12) | func Test_FS_Disallows_Parent_Folders(t *testing.T) {
  function Test_FS_Hides_embed_go (line 27) | func Test_FS_Hides_embed_go(t *testing.T) {
  function Test_FS_Prioritizes_Disk (line 38) | func Test_FS_Prioritizes_Disk(t *testing.T) {
  function Test_FS_Uses_Embed_If_No_Disk (line 62) | func Test_FS_Uses_Embed_If_No_Disk(t *testing.T) {
  function Test_FS_ReadDirFile (line 86) | func Test_FS_ReadDirFile(t *testing.T) {

FILE: handler.go
  type Handler (line 22) | type Handler

FILE: home.go
  type Home (line 25) | type Home struct

FILE: internal/defaults/defaults.go
  function String (line 3) | func String(s1, s2 string) string {
  function Int (line 10) | func Int(i1, i2 int) int {
  function Int64 (line 17) | func Int64(i1, i2 int64) int64 {
  function Float32 (line 24) | func Float32(i1, i2 float32) float32 {
  function Float64 (line 31) | func Float64(i1, i2 float64) float64 {

FILE: internal/defaults/defaults_test.go
  function Test_String (line 9) | func Test_String(t *testing.T) {
  function Test_Int (line 18) | func Test_Int(t *testing.T) {
  function Test_Int64 (line 27) | func Test_Int64(t *testing.T) {
  function Test_Float32 (line 36) | func Test_Float32(t *testing.T) {
  function Test_Float64 (line 45) | func Test_Float64(t *testing.T) {

FILE: internal/env/env.go
  function Load (line 16) | func Load(filenames ...string) error {
  function Get (line 22) | func Get(key, fallback string) string {
  function MustGet (line 31) | func MustGet(key string) (string, error) {
  function Environ (line 40) | func Environ() []string {
  function GoPath (line 46) | func GoPath() string {
  function Set (line 55) | func Set(key, value string) {
  function Temp (line 61) | func Temp(f func()) {

FILE: internal/fakesmtp/connection.go
  type Connection (line 10) | type Connection struct
    method write (line 19) | func (c *Connection) write(s string) {
    method read (line 25) | func (c *Connection) read() string {

FILE: internal/fakesmtp/server.go
  type Server (line 16) | type Server struct
    method Start (line 23) | func (s *Server) Start(port string) error {
    method Handle (line 41) | func (s *Server) Handle(c *Connection) {
    method readHello (line 56) | func (s *Server) readHello(c *Connection) {
    method readSender (line 65) | func (s *Server) readSender(c *Connection) {
    method readRecipients (line 72) | func (s *Server) readRecipients(c *Connection) {
    method readData (line 86) | func (s *Server) readData(c *Connection) {
    method addMessageLine (line 102) | func (s *Server) addMessageLine(text string) {
    method LastMessage (line 107) | func (s *Server) LastMessage() string {
    method Messages (line 116) | func (s *Server) Messages() []string {
    method Clear (line 121) | func (s *Server) Clear() {
  function New (line 129) | func New(port string) (*Server, error) {

FILE: internal/httpx/content_type.go
  function ContentType (line 10) | func ContentType(req *http.Request) string {

FILE: internal/httpx/content_type_test.go
  function Test_ContentType (line 10) | func Test_ContentType(t *testing.T) {

FILE: internal/meta/meta.go
  type BuildTags (line 12) | type BuildTags
  type App (line 15) | type App struct
  function New (line 24) | func New(root string) App {

FILE: internal/meta/meta_test.go
  function Test_New_Defaults (line 11) | func Test_New_Defaults(t *testing.T) {
  function Test_New_With_DatabaseYML (line 22) | func Test_New_With_DatabaseYML(t *testing.T) {
  function Test_New_With_TOML (line 34) | func Test_New_With_TOML(t *testing.T) {
  function Test_New_TOML_Priority_Over_DatabaseYML (line 50) | func Test_New_TOML_Priority_Over_DatabaseYML(t *testing.T) {
  function Test_New_No_Files (line 71) | func Test_New_No_Files(t *testing.T) {

FILE: internal/nulls/nulls.go
  type Time (line 11) | type Time struct
    method Scan (line 17) | func (t *Time) Scan(value any) error {
    method Parse (line 35) | func (t *Time) Parse(s string) error {
    method Value (line 56) | func (t Time) Value() (driver.Value, error) {
    method UnmarshalJSON (line 64) | func (t *Time) UnmarshalJSON(data []byte) error {
    method MarshalJSON (line 76) | func (t Time) MarshalJSON() ([]byte, error) {
    method String (line 84) | func (t Time) String() string {
  function NewTime (line 93) | func NewTime(t time.Time) Time {

FILE: internal/testdata/embedded/embed.go
  function FS (line 10) | func FS() embed.FS {

FILE: mail/attachment.go
  type Attachment (line 6) | type Attachment struct

FILE: mail/body.go
  type Body (line 4) | type Body struct

FILE: mail/dialer.go
  type Dialer (line 17) | type Dialer struct
    method dial (line 60) | func (d *Dialer) dial() (sendCloser, error) {
    method tlsConfig (line 127) | func (d *Dialer) tlsConfig() *tls.Config {
    method dialAndSend (line 169) | func (d *Dialer) dialAndSend(m ...*smtpMessage) error {
  function newDialer (line 43) | func newDialer(host string, port int, username, password string) *Dialer {
  type StartTLSPolicy (line 136) | type StartTLSPolicy
    method String (line 144) | func (policy *StartTLSPolicy) String() string {
  constant opportunisticStartTLS (line 139) | opportunisticStartTLS StartTLSPolicy = iota
  constant mandatoryStartTLS (line 140) | mandatoryStartTLS
  constant noStartTLS (line 141) | noStartTLS = -1
  type startTLSUnsupportedError (line 157) | type startTLSUnsupportedError struct
    method Error (line 161) | func (e startTLSUnsupportedError) Error() string {
  function addr (line 165) | func addr(host string, port int) string {
  type smtpSender (line 185) | type smtpSender struct
    method retryError (line 191) | func (c *smtpSender) retryError(err error) bool {
    method Send (line 203) | func (c *smtpSender) Send(from string, to []string, msg io.WriterTo) e...
    method Close (line 241) | func (c *smtpSender) Close() error {
  type smtpClient (line 253) | type smtpClient interface
  type sendCloser (line 265) | type sendCloser interface
  type sender (line 270) | type sender interface

FILE: mail/mail.go
  function NewMessage (line 24) | func NewMessage() Message {
  function NewFromData (line 34) | func NewFromData(data render.Data) Message {
  function New (line 41) | func New(c buffalo.Context) Message {

FILE: mail/mail_test.go
  function Test_NewFromData (line 14) | func Test_NewFromData(t *testing.T) {
  function Test_New (line 22) | func Test_New(t *testing.T) {

FILE: mail/message.go
  type Message (line 14) | type Message struct
    method merge (line 28) | func (m *Message) merge(data render.Data) render.Data {
    method AddBody (line 39) | func (m *Message) AddBody(r render.Renderer, data render.Data) error {
    method AddBodies (line 57) | func (m *Message) AddBodies(data render.Data, renderers ...render.Rend...
    method AddAttachment (line 69) | func (m *Message) AddAttachment(name, contentType string, r io.Reader)...
    method AddEmbedded (line 82) | func (m *Message) AddEmbedded(name string, r io.Reader) error {
    method SetHeader (line 93) | func (m *Message) SetHeader(field, value string) {

FILE: mail/sender.go
  type Sender (line 4) | type Sender interface
  type BatchSender (line 10) | type BatchSender interface

FILE: mail/smtp_auth.go
  type loginAuth (line 14) | type loginAuth struct
    method Start (line 20) | func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, er...
    method Next (line 32) | func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {

FILE: mail/smtp_errors.go
  type sendError (line 10) | type sendError struct
    method Error (line 16) | func (err *sendError) Error() string {

FILE: mail/smtp_message.go
  type smtpMessage (line 15) | type smtpMessage struct
    method applySettings (line 53) | func (m *smtpMessage) applySettings(settings []messageSetting) {
    method setHeader (line 69) | func (m *smtpMessage) setHeader(field string, value ...string) {
    method encodeHeader (line 74) | func (m *smtpMessage) encodeHeader(values []string) {
    method encodeString (line 80) | func (m *smtpMessage) encodeString(value string) string {
    method setBody (line 84) | func (m *smtpMessage) setBody(contentType, body string, settings ...pa...
    method setBodyWriter (line 88) | func (m *smtpMessage) setBodyWriter(contentType string, f func(io.Writ...
    method addAlternative (line 92) | func (m *smtpMessage) addAlternative(contentType, body string, setting...
    method addAlternativeWriter (line 103) | func (m *smtpMessage) addAlternativeWriter(contentType string, f func(...
    method newPart (line 107) | func (m *smtpMessage) newPart(contentType string, f func(io.Writer) er...
    method attach (line 147) | func (m *smtpMessage) attach(filename string, settings ...fileSetting) {
    method embed (line 151) | func (m *smtpMessage) embed(filename string, settings ...fileSetting) {
    method formatDate (line 173) | func (m *smtpMessage) formatDate(date time.Time) string {
    method appendFile (line 177) | func (m *smtpMessage) appendFile(list []*file, f *file, settings []fil...
  type smtpHeader (line 27) | type smtpHeader
  type part (line 29) | type part struct
  function newSMTPMessage (line 35) | func newSMTPMessage(settings ...messageSetting) *smtpMessage {
  type messageSetting (line 59) | type messageSetting
  type encoding (line 61) | type encoding
  constant encodingQuotedPrintable (line 64) | encodingQuotedPrintable encoding = "quoted-printable"
  constant encodingBase64 (line 65) | encodingBase64          encoding = "base64"
  constant encodingUnencoded (line 66) | encodingUnencoded       encoding = "8bit"
  function newCopier (line 96) | func newCopier(s string) func(io.Writer) error {
  type partSetting (line 121) | type partSetting
  function setPartEncoding (line 123) | func setPartEncoding(e encoding) partSetting {
  type file (line 129) | type file struct
    method setHeader (line 135) | func (f *file) setHeader(field, value string) {
  type fileSetting (line 139) | type fileSetting
  function setCopyFunc (line 141) | func setCopyFunc(f func(io.Writer) error) fileSetting {
  function fileFromFilename (line 155) | func fileFromFilename(name string) *file {

FILE: mail/smtp_mime.go
  type mimeEncoder (line 14) | type mimeEncoder struct

FILE: mail/smtp_send.go
  function sendSMTP (line 13) | func sendSMTP(s sender, msg ...*smtpMessage) []error {
  function sendSingle (line 24) | func sendSingle(s sender, m *smtpMessage) error {
  method getFrom (line 42) | func (m *smtpMessage) getFrom() (string, error) {
  method getRecipients (line 54) | func (m *smtpMessage) getRecipients() ([]string, error) {
  function addAddress (line 78) | func addAddress(list []string, addr string) []string {
  function parseAddress (line 85) | func parseAddress(field string) (string, error) {

FILE: mail/smtp_sender.go
  type SMTPSender (line 10) | type SMTPSender struct
    method Send (line 16) | func (sm SMTPSender) Send(message Message) error {
    method SendBatch (line 22) | func (sm SMTPSender) SendBatch(messages ...Message) (errorsByMessages ...
    method prepareMessage (line 36) | func (sm SMTPSender) prepareMessage(message Message) *smtpMessage {
    method addBodies (line 55) | func (sm SMTPSender) addBodies(message Message, gm *smtpMessage) {
    method addAttachments (line 69) | func (sm SMTPSender) addAttachments(message Message, gm *smtpMessage) {
  function NewSMTPSender (line 88) | func NewSMTPSender(host string, port string, user string, password strin...

FILE: mail/smtp_sender_test.go
  constant smtpPort (line 17) | smtpPort = "2002"
  function init (line 19) | func init() {
  function TestSendPlain (line 27) | func TestSendPlain(t *testing.T) {

FILE: mail/smtp_writeto.go
  method WriteTo (line 17) | func (m *smtpMessage) WriteTo(w io.Writer) (int64, error) {
  method hasMixedPart (line 61) | func (m *smtpMessage) hasMixedPart() bool {
  method hasRelatedPart (line 65) | func (m *smtpMessage) hasRelatedPart() bool {
  method hasAlternativePart (line 69) | func (m *smtpMessage) hasAlternativePart() bool {
  type messageWriter (line 73) | type messageWriter struct
    method writeMessage (line 23) | func (w *messageWriter) writeMessage(m *smtpMessage) {
    method openMultipart (line 82) | func (w *messageWriter) openMultipart(mimeType, boundary string) {
    method createPart (line 101) | func (w *messageWriter) createPart(h map[string][]string) {
    method closeMultipart (line 105) | func (w *messageWriter) closeMultipart() {
    method writePart (line 112) | func (w *messageWriter) writePart(p *part, charset string) {
    method addFiles (line 120) | func (w *messageWriter) addFiles(files []*file, isAttachment bool) {
    method Write (line 154) | func (w *messageWriter) Write(p []byte) (int, error) {
    method writeString (line 165) | func (w *messageWriter) writeString(s string) {
    method writeHeader (line 174) | func (w *messageWriter) writeHeader(k string, v ...string) {
    method writeLine (line 211) | func (w *messageWriter) writeLine(s string, charsLeft int) string {
    method writeHeaders (line 241) | func (w *messageWriter) writeHeaders(h map[string][]string) {
    method writeBody (line 253) | func (w *messageWriter) writeBody(f func(io.Writer) error, enc encodin...
  constant maxLineLen (line 275) | maxLineLen = 76
  type base64LineWriter (line 277) | type base64LineWriter struct
    method Write (line 286) | func (w *base64LineWriter) Write(p []byte) (int, error) {
  function newBase64LineWriter (line 282) | func newBase64LineWriter(w io.Writer) *base64LineWriter {

FILE: method_override.go
  function MethodOverride (line 15) | func MethodOverride(res http.ResponseWriter, req *http.Request) {

FILE: method_override_test.go
  function Test_MethodOverride (line 13) | func Test_MethodOverride(t *testing.T) {

FILE: middleware.go
  type MiddlewareFunc (line 24) | type MiddlewareFunc
  constant funcKeyDelimeter (line 26) | funcKeyDelimeter = ":"
  method Use (line 32) | func (a *App) Use(mw ...MiddlewareFunc) {
  type MiddlewareStack (line 37) | type MiddlewareStack struct
    method String (line 42) | func (ms MiddlewareStack) String() string {
    method clone (line 51) | func (ms *MiddlewareStack) clone() *MiddlewareStack {
    method Clear (line 61) | func (ms *MiddlewareStack) Clear() {
    method Use (line 70) | func (ms *MiddlewareStack) Use(mw ...MiddlewareFunc) {
    method Remove (line 79) | func (ms *MiddlewareStack) Remove(mws ...MiddlewareFunc) {
    method Skip (line 104) | func (ms *MiddlewareStack) Skip(mw MiddlewareFunc, handlers ...Handler) {
    method Replace (line 113) | func (ms *MiddlewareStack) Replace(mw1 MiddlewareFunc, mw2 MiddlewareF...
    method handler (line 154) | func (ms *MiddlewareStack) handler(info RouteInfo) Handler {
  function assertMiddleware (line 136) | func assertMiddleware(handler Handler) Handler {
  function newMiddlewareStack (line 176) | func newMiddlewareStack(mws ...MiddlewareFunc) *MiddlewareStack {
  function funcKey (line 183) | func funcKey(funcs ...any) string {
  function ptrName (line 208) | func ptrName(ptr uintptr) string {
  function setFuncKey (line 218) | func setFuncKey(f any, name string) {

FILE: middleware_test.go
  function Test_App_Use (line 14) | func Test_App_Use(t *testing.T) {
  function Test_Middleware_Replace (line 40) | func Test_Middleware_Replace(t *testing.T) {
  function Test_Middleware_Skip (line 76) | func Test_Middleware_Skip(t *testing.T) {
  type carsResource (line 126) | type carsResource struct
    method Show (line 130) | func (ur *carsResource) Show(c Context) error {
    method List (line 134) | func (ur *carsResource) List(c Context) error {
  function Test_Middleware_Skip_Resource (line 139) | func Test_Middleware_Skip_Resource(t *testing.T) {
  function Test_Middleware_Clear (line 188) | func Test_Middleware_Clear(t *testing.T) {
  function Test_Middleware_Remove (line 204) | func Test_Middleware_Remove(t *testing.T) {
  function Test_AssertMiddleware_NilStatus200 (line 247) | func Test_AssertMiddleware_NilStatus200(t *testing.T) {

FILE: not_found_test.go
  function Test_App_Dev_NotFound (line 12) | func Test_App_Dev_NotFound(t *testing.T) {
  function Test_App_Dev_NotFound_JSON (line 28) | func Test_App_Dev_NotFound_JSON(t *testing.T) {
  function Test_App_Override_NotFound (line 45) | func Test_App_Override_NotFound(t *testing.T) {

FILE: options.go
  type Options (line 17) | type Options struct
  type PreWare (line 77) | type PreWare
  function NewOptions (line 80) | func NewOptions() Options {
  function optionsWithDefaults (line 84) | func optionsWithDefaults(opts Options) Options {

FILE: options_test.go
  function TestOptions_NewOptions (line 12) | func TestOptions_NewOptions(t *testing.T) {

FILE: plugins/cache.go
  type cachedPlugin (line 16) | type cachedPlugin struct
  type cachedPlugins (line 21) | type cachedPlugins
  function findInCache (line 53) | func findInCache(path string) (cachedPlugin, bool) {
  function saveCache (line 60) | func saveCache() error {
  function sum (line 74) | func sum(path string) string {
  function addToCache (line 90) | func addToCache(path string, cp cachedPlugin) {

FILE: plugins/command.go
  type Command (line 4) | type Command struct
  type Commands (line 21) | type Commands

FILE: plugins/decorate.go
  function Decorate (line 19) | func Decorate(c Command) *cobra.Command {
  function LookPath (line 62) | func LookPath(s string) (string, error) {

FILE: plugins/events.go
  constant EvtSetupStarted (line 4) | EvtSetupStarted  = "buffalo-plugins:setup:started"
  constant EvtSetupErr (line 5) | EvtSetupErr      = "buffalo-plugins:setup:err"
  constant EvtSetupFinished (line 6) | EvtSetupFinished = "buffalo-plugins:setup:finished"

FILE: plugins/log.go
  function log (line 5) | func log(_ string, fn func() error) error {

FILE: plugins/log_debug.go
  function log (line 10) | func log(name string, fn func() error) error {

FILE: plugins/plugcmds/available.go
  function NewAvailable (line 15) | func NewAvailable() *Available {
  type Available (line 23) | type Available struct
    method Cmd (line 39) | func (a *Available) Cmd() *cobra.Command {
    method Commands (line 50) | func (a *Available) Commands() []*cobra.Command {
    method Add (line 67) | func (a *Available) Add(bufCmd string, cmd *cobra.Command) error {
    method Mount (line 91) | func (a *Available) Mount(cmd *cobra.Command) {
    method Encode (line 102) | func (a *Available) Encode(w io.Writer) error {
    method Listen (line 114) | func (a *Available) Listen(fn func(e events.Event) error) error {
    method ListenFor (line 120) | func (a *Available) ListenFor(rx string, fn func(e events.Event) error...
  type plug (line 27) | type plug struct
    method String (line 33) | func (p plug) String() string {
  function buildListen (line 138) | func buildListen(fn func(e events.Event) error) *cobra.Command {

FILE: plugins/plugcmds/available_test.go
  function Test_Available_Add (line 13) | func Test_Available_Add(t *testing.T) {
  function Test_Available_Encode (line 27) | func Test_Available_Encode(t *testing.T) {
  function Test_Available_Listen (line 45) | func Test_Available_Listen(t *testing.T) {

FILE: plugins/plugcmds/plug_map.go
  type plugMap (line 14) | type plugMap struct
    method Delete (line 19) | func (m *plugMap) Delete(key string) {
    method Load (line 27) | func (m *plugMap) Load(key string) (plug, bool) {
    method LoadOrStore (line 38) | func (m *plugMap) LoadOrStore(key string, value plug) (plug, bool) {
    method Range (line 45) | func (m *plugMap) Range(f func(key string, value plug) bool) {
    method Store (line 60) | func (m *plugMap) Store(key string, value plug) {
    method Keys (line 65) | func (m *plugMap) Keys() []string {

FILE: plugins/plugcmds/plug_map_test.go
  function Test_plugMap (line 12) | func Test_plugMap(t *testing.T) {

FILE: plugins/plugdeps/command.go
  type Command (line 6) | type Command struct
    method String (line 13) | func (p Command) String() string {

FILE: plugins/plugdeps/plugdeps.go
  function List (line 19) | func List(app meta.App) (*Plugins, error) {
  function listLocal (line 47) | func listLocal(app meta.App) (*Plugins, error) {
  function ConfigPath (line 76) | func ConfigPath(app meta.App) string {
  function On (line 83) | func On(app meta.App) bool {

FILE: plugins/plugdeps/plugdeps_test.go
  function Test_ConfigPath (line 27) | func Test_ConfigPath(t *testing.T) {
  function Test_List_Off (line 34) | func Test_List_Off(t *testing.T) {
  function Test_List_On (line 44) | func Test_List_On(t *testing.T) {
  constant eToml (line 61) | eToml = `[[plugin]]

FILE: plugins/plugdeps/plugin.go
  type Plugin (line 10) | type Plugin struct
    method String (line 19) | func (p Plugin) String() string {
    method key (line 24) | func (p Plugin) key() string {

FILE: plugins/plugdeps/plugins.go
  type Plugins (line 13) | type Plugins struct
    method Encode (line 19) | func (plugs *Plugins) Encode(w io.Writer) error {
    method Decode (line 31) | func (plugs *Plugins) Decode(r io.Reader) error {
    method List (line 45) | func (plugs *Plugins) List() []Plugin {
    method Add (line 63) | func (plugs *Plugins) Add(pp ...Plugin) {
    method Remove (line 72) | func (plugs *Plugins) Remove(pp ...Plugin) {
  function New (line 81) | func New() *Plugins {
  type tomlPlugins (line 89) | type tomlPlugins struct

FILE: plugins/plugdeps/plugins_test.go
  function Test_Plugins_Encode (line 12) | func Test_Plugins_Encode(t *testing.T) {
  function Test_Plugins_Decode (line 28) | func Test_Plugins_Decode(t *testing.T) {
  function Test_Plugins_Remove (line 43) | func Test_Plugins_Remove(t *testing.T) {

FILE: plugins/plugins.go
  constant timeoutEnv (line 22) | timeoutEnv = "BUFFALO_PLUGIN_TIMEOUT"
  type List (line 42) | type List
  function Available (line 64) | func Available() (List, error) {
  function askBin (line 140) | func askBin(ctx context.Context, path string) Commands {
  function ignorePath (line 184) | func ignorePath(p string) bool {
  function listPlugDeps (line 194) | func listPlugDeps(app meta.App) (List, error) {

FILE: plugins/plugins_test.go
  function TestAskBin_respectsTimeout (line 14) | func TestAskBin_respectsTimeout(t *testing.T) {

FILE: render/auto.go
  type ErrRedirect (line 20) | type ErrRedirect struct
    method Error (line 25) | func (ErrRedirect) Error() string {
  function Auto (line 44) | func Auto(ctx context.Context, i any) Renderer {
  method Auto (line 64) | func (e *Engine) Auto(ctx context.Context, i any) Renderer {
  type htmlAutoRenderer (line 85) | type htmlAutoRenderer struct
    method ContentType (line 90) | func (htmlAutoRenderer) ContentType() string {
    method Render (line 94) | func (ir htmlAutoRenderer) Render(w io.Writer, data Data) error {
    method redirect (line 152) | func (ir htmlAutoRenderer) redirect(name name.Ident, w io.Writer, data...
    method typeName (line 193) | func (ir htmlAutoRenderer) typeName() string {
    method isPlural (line 205) | func (ir htmlAutoRenderer) isPlural() bool {

FILE: render/auto_test.go
  type Car (line 15) | type Car struct
  type Cars (line 20) | type Cars
  function Test_Auto_DefaultContentType (line 22) | func Test_Auto_DefaultContentType(t *testing.T) {
  function Test_Auto_JSON (line 41) | func Test_Auto_JSON(t *testing.T) {
  function Test_Auto_XML (line 56) | func Test_Auto_XML(t *testing.T) {
  function Test_Auto_HTML_List (line 71) | func Test_Auto_HTML_List(t *testing.T) {
  function Test_Auto_HTML_List_Plural (line 98) | func Test_Auto_HTML_List_Plural(t *testing.T) {
  function Test_Auto_HTML_Show (line 132) | func Test_Auto_HTML_Show(t *testing.T) {
  function Test_Auto_HTML_New (line 156) | func Test_Auto_HTML_New(t *testing.T) {
  function Test_Auto_HTML_Create (line 180) | func Test_Auto_HTML_Create(t *testing.T) {
  function Test_Auto_HTML_Create_Redirect (line 204) | func Test_Auto_HTML_Create_Redirect(t *testing.T) {
  function Test_Auto_HTML_Create_Redirect_Error (line 221) | func Test_Auto_HTML_Create_Redirect_Error(t *testing.T) {
  function Test_Auto_HTML_Create_Nested_Redirect (line 249) | func Test_Auto_HTML_Create_Nested_Redirect(t *testing.T) {
  function Test_Auto_HTML_Destroy_Nested_Redirect (line 267) | func Test_Auto_HTML_Destroy_Nested_Redirect(t *testing.T) {
  function Test_Auto_HTML_Edit (line 285) | func Test_Auto_HTML_Edit(t *testing.T) {
  function Test_Auto_HTML_Update (line 309) | func Test_Auto_HTML_Update(t *testing.T) {
  function Test_Auto_HTML_Update_Redirect (line 334) | func Test_Auto_HTML_Update_Redirect(t *testing.T) {
  function Test_Auto_HTML_Update_Redirect_Error (line 352) | func Test_Auto_HTML_Update_Redirect_Error(t *testing.T) {
  function Test_Auto_HTML_Destroy_Redirect (line 381) | func Test_Auto_HTML_Destroy_Redirect(t *testing.T) {
  function Test_Auto_HTML_List_Plural_MultiWord (line 399) | func Test_Auto_HTML_List_Plural_MultiWord(t *testing.T) {
  function Test_Auto_HTML_List_Plural_MultiWord_Dashed (line 433) | func Test_Auto_HTML_List_Plural_MultiWord_Dashed(t *testing.T) {
  function Test_Auto_HTML_Show_MultiWord_Dashed (line 467) | func Test_Auto_HTML_Show_MultiWord_Dashed(t *testing.T) {

FILE: render/download.go
  type downloadRenderer (line 13) | type downloadRenderer struct
    method ContentType (line 19) | func (r downloadRenderer) ContentType() string {
    method Render (line 29) | func (r downloadRenderer) Render(w io.Writer, d Data) error {
  function Download (line 65) | func Download(ctx context.Context, name string, r io.Reader) Renderer {
  method Download (line 89) | func (e *Engine) Download(ctx context.Context, name string, r io.Reader)...
  type responsible (line 93) | type responsible interface

FILE: render/download_test.go
  type dlRenderer (line 15) | type dlRenderer
  type dlContext (line 17) | type dlContext struct
    method Response (line 22) | func (c dlContext) Response() http.ResponseWriter {
  function Test_Download_KnownExtension (line 28) | func Test_Download_KnownExtension(t *testing.T) {
  function Test_Download_UnknownExtension (line 51) | func Test_Download_UnknownExtension(t *testing.T) {
  function Test_InvalidContext (line 73) | func Test_InvalidContext(t *testing.T) {

FILE: render/func.go
  type RendererFunc (line 7) | type RendererFunc
  type funcRenderer (line 9) | type funcRenderer struct
    method ContentType (line 16) | func (s funcRenderer) ContentType() string {
    method Render (line 22) | func (s funcRenderer) Render(w io.Writer, data Data) error {
  function Func (line 29) | func Func(s string, fn RendererFunc) Renderer {
  method Func (line 39) | func (e *Engine) Func(s string, fn RendererFunc) Renderer {

FILE: render/func_test.go
  function Test_Func (line 11) | func Test_Func(t *testing.T) {

FILE: render/helpers.go
  function init (line 13) | func init() {

FILE: render/html.go
  function HTML (line 17) | func HTML(names ...string) Renderer {
  method HTML (line 31) | func (e *Engine) HTML(names ...string) Renderer {
  function MDTemplateEngine (line 52) | func MDTemplateEngine(input string, data map[string]any, helpers map[str...

FILE: render/html_test.go
  constant htmlLayout (line 12) | htmlLayout = "layout.html"
  constant htmlAltLayout (line 13) | htmlAltLayout = "alt_layout.plush.html"
  constant htmlTemplate (line 14) | htmlTemplate = "my-template.html"
  function Test_HTML_WithoutLayout (line 16) | func Test_HTML_WithoutLayout(t *testing.T) {
  function Test_HTML_WithLayout (line 37) | func Test_HTML_WithLayout(t *testing.T) {
  function Test_HTML_WithLayout_Override (line 63) | func Test_HTML_WithLayout_Override(t *testing.T) {
  function Test_HTML_LeadingSlash (line 93) | func Test_HTML_LeadingSlash(t *testing.T) {

FILE: render/js.go
  function JavaScript (line 9) | func JavaScript(names ...string) Renderer {
  method JavaScript (line 23) | func (e *Engine) JavaScript(names ...string) Renderer {

FILE: render/js_test.go
  constant jsLayout (line 12) | jsLayout = "layout.js"
  constant jsAltLayout (line 13) | jsAltLayout = "alt_layout.plush.js"
  constant jsTemplate (line 14) | jsTemplate = "my-template.js"
  function Test_JavaScript_WithoutLayout (line 16) | func Test_JavaScript_WithoutLayout(t *testing.T) {
  function Test_JavaScript_WithLayout (line 37) | func Test_JavaScript_WithLayout(t *testing.T) {
  function Test_JavaScript_WithLayout_Override (line 63) | func Test_JavaScript_WithLayout_Override(t *testing.T) {
  function Test_JavaScript_Partial_Without_Extension (line 93) | func Test_JavaScript_Partial_Without_Extension(t *testing.T) {
  function Test_JavaScript_Partial (line 120) | func Test_JavaScript_Partial(t *testing.T) {
  function Test_JavaScript_HTML_Partial (line 148) | func Test_JavaScript_HTML_Partial(t *testing.T) {

FILE: render/json.go
  type jsonRenderer (line 8) | type jsonRenderer struct
    method ContentType (line 12) | func (s jsonRenderer) ContentType() string {
    method Render (line 16) | func (s jsonRenderer) Render(w io.Writer, data Data) error {
  function JSON (line 22) | func JSON(v any) Renderer {
  method JSON (line 28) | func (e *Engine) JSON(v any) Renderer {

FILE: render/json_test.go
  function Test_JSON (line 11) | func Test_JSON(t *testing.T) {

FILE: render/markdown_test.go
  constant mdTemplate (line 12) | mdTemplate = "my-template.md"
  function Test_MD_WithoutLayout (line 14) | func Test_MD_WithoutLayout(t *testing.T) {
  function Test_MD_WithLayout (line 35) | func Test_MD_WithLayout(t *testing.T) {

FILE: render/options.go
  type Helpers (line 10) | type Helpers
  type Options (line 13) | type Options struct

FILE: render/partials_test.go
  function Test_Template_Partial (line 12) | func Test_Template_Partial(t *testing.T) {
  function Test_Template_PartialCustomFeeder (line 39) | func Test_Template_PartialCustomFeeder(t *testing.T) {
  function Test_Template_Partial_WithoutExtension (line 79) | func Test_Template_Partial_WithoutExtension(t *testing.T) {
  function Test_Template_Partial_Form (line 106) | func Test_Template_Partial_Form(t *testing.T) {
  function Test_Template_Partial_With_For (line 135) | func Test_Template_Partial_With_For(t *testing.T) {
  function Test_Template_Partial_With_For_And_Local (line 170) | func Test_Template_Partial_With_For_And_Local(t *testing.T) {
  function Test_Template_Partial_Recursive_With_Global_And_Local_Context (line 205) | func Test_Template_Partial_Recursive_With_Global_And_Local_Context(t *te...
  function Test_Template_Partial_With_Layout (line 233) | func Test_Template_Partial_With_Layout(t *testing.T) {

FILE: render/plain.go
  function Plain (line 9) | func Plain(names ...string) Renderer {
  method Plain (line 20) | func (e *Engine) Plain(names ...string) Renderer {

FILE: render/plain_test.go
  function Test_Plain (line 11) | func Test_Plain(t *testing.T) {

FILE: render/render.go
  type Engine (line 14) | type Engine struct
  function New (line 20) | func New(opts Options) *Engine {
  function defaultHelpers (line 68) | func defaultHelpers() Helpers {

FILE: render/render_test.go
  type Widget (line 9) | type Widget struct
    method ToPath (line 13) | func (w Widget) ToPath() string {
  function NewEngine (line 17) | func NewEngine() *Engine {
  type rendFriend (line 24) | type rendFriend
  function TestMain (line 26) | func TestMain(m *testing.M) {
  function init (line 31) | func init() {

FILE: render/renderer.go
  type Renderer (line 7) | type Renderer interface
  type Data (line 14) | type Data

FILE: render/sse.go
  type sse (line 9) | type sse struct
    method String (line 14) | func (s *sse) String() string {
    method Bytes (line 19) | func (s *sse) Bytes() []byte {
  type EventSource (line 26) | type EventSource struct
    method Write (line 31) | func (es *EventSource) Write(t string, d any) error {
    method Flush (line 43) | func (es *EventSource) Flush() {
    method CloseNotify (line 53) | func (es *EventSource) CloseNotify() <-chan bool {
  type closeNotifier (line 47) | type closeNotifier interface
  function NewEventSource (line 63) | func NewEventSource(w http.ResponseWriter) (*EventSource, error) {

FILE: render/string.go
  type stringRenderer (line 8) | type stringRenderer struct
    method ContentType (line 13) | func (s stringRenderer) ContentType() string {
    method Render (line 17) | func (s stringRenderer) Render(w io.Writer, data Data) error {
  function String (line 33) | func String(s string, args ...any) Renderer {
  method String (line 41) | func (e *Engine) String(s string, args ...any) Renderer {

FILE: render/string_map.go
  type stringMap (line 11) | type stringMap struct
    method Delete (line 16) | func (m *stringMap) Delete(key string) {
    method Load (line 24) | func (m *stringMap) Load(key string) (string, bool) {
    method LoadOrStore (line 35) | func (m *stringMap) LoadOrStore(key string, value string) (string, boo...
    method Range (line 42) | func (m *stringMap) Range(f func(key string, value string) bool) {
    method Store (line 57) | func (m *stringMap) Store(key string, value string) {
    method Keys (line 62) | func (m *stringMap) Keys() []string {
    method Clear (line 73) | func (m *stringMap) Clear() {

FILE: render/string_map_test.go
  function Test_stringMap (line 10) | func Test_stringMap(t *testing.T) {

FILE: render/string_test.go
  function Test_String (line 11) | func Test_String(t *testing.T) {

FILE: render/template.go
  type templateRenderer (line 20) | type templateRenderer struct
    method ContentType (line 27) | func (s *templateRenderer) ContentType() string {
    method resolve (line 31) | func (s *templateRenderer) resolve(name string) ([]byte, fs.FileInfo, ...
    method Render (line 57) | func (s *templateRenderer) Render(w io.Writer, data Data) error {
    method updateAliases (line 77) | func (s *templateRenderer) updateAliases() error {
    method partialFeeder (line 135) | func (s *templateRenderer) partialFeeder(name string) (string, error) {
    method exec (line 146) | func (s *templateRenderer) exec(name string, data Data) (template.HTML...
    method localizedName (line 184) | func (s *templateRenderer) localizedName(name string, data Data) string {
    method localizedResolve (line 215) | func (s *templateRenderer) localizedResolve(name string, data Data) ([...
    method addTemplateMetadata (line 249) | func (s *templateRenderer) addTemplateMetadata(data Data, fileName, ex...
    method extsAndBase (line 277) | func (s *templateRenderer) extsAndBase(name string) ([]string, string) {
    method exts (line 295) | func (s *templateRenderer) exts(name string) []string {
    method assetPath (line 312) | func (s *templateRenderer) assetPath(file string) (string, error) {
  function fixExtension (line 118) | func fixExtension(name string, ct string) string {
  function Template (line 339) | func Template(c string, names ...string) Renderer {
  method Template (line 350) | func (e *Engine) Template(c string, names ...string) Renderer {

FILE: render/template_engine.go
  type TemplateEngine (line 9) | type TemplateEngine
  function GoTemplateEngine (line 12) | func GoTemplateEngine(input string, data map[string]any, helpers map[str...

FILE: render/template_helpers.go
  type helperTag (line 14) | type helperTag struct
  method addAssetsHelpers (line 19) | func (s *templateRenderer) addAssetsHelpers(helpers Helpers) Helpers {
  function assetPathFor (line 48) | func assetPathFor(file string) string {
  function loadManifest (line 56) | func loadManifest(manifest io.Reader) error {

FILE: render/template_helpers_test.go
  function tag (line 15) | func tag(name string) (tagHelper, error) {
  function Test_javascriptTag (line 33) | func Test_javascriptTag(t *testing.T) {
  function Test_javascriptTag_Options (line 44) | func Test_javascriptTag_Options(t *testing.T) {
  function Test_stylesheetTag (line 55) | func Test_stylesheetTag(t *testing.T) {
  function Test_stylesheetTag_Options (line 66) | func Test_stylesheetTag_Options(t *testing.T) {
  function Test_imgTag (line 77) | func Test_imgTag(t *testing.T) {
  function Test_imgTag_Options (line 88) | func Test_imgTag_Options(t *testing.T) {

FILE: render/template_test.go
  function Test_Template (line 12) | func Test_Template(t *testing.T) {
  function Test_AssetPath (line 32) | func Test_AssetPath(t *testing.T) {
  function Test_AssetPathNoManifest (line 72) | func Test_AssetPathNoManifest(t *testing.T) {
  function Test_AssetPathNoManifestCorrupt (line 98) | func Test_AssetPathNoManifestCorrupt(t *testing.T) {
  function Test_Template_resolve_DefaultLang_Plush (line 135) | func Test_Template_resolve_DefaultLang_Plush(t *testing.T) {
  function Test_Template_resolve_UserLang_Plush (line 160) | func Test_Template_resolve_UserLang_Plush(t *testing.T) {
  function Test_Template_resolve_DefaultLang_Legacy (line 185) | func Test_Template_resolve_DefaultLang_Legacy(t *testing.T) {
  function Test_Template_resolve_UserLang_Legacy (line 210) | func Test_Template_resolve_UserLang_Legacy(t *testing.T) {
  function Test_Template_resolve_DefaultLang_Mixed (line 235) | func Test_Template_resolve_DefaultLang_Mixed(t *testing.T) {
  function Test_Template_resolve_UserLang_Mixed (line 262) | func Test_Template_resolve_UserLang_Mixed(t *testing.T) {
  function Test_Template_resolve_FullLocale_ShortFile (line 290) | func Test_Template_resolve_FullLocale_ShortFile(t *testing.T) {
  function Test_Template_resolve_LangOnly_FullFile (line 315) | func Test_Template_resolve_LangOnly_FullFile(t *testing.T) {
  function Test_Template_resolve_FullLocale_ShortFile_Legacy (line 340) | func Test_Template_resolve_FullLocale_ShortFile_Legacy(t *testing.T) {
  function Test_Template_resolve_LangOnly_FullFile_Legacy (line 365) | func Test_Template_resolve_LangOnly_FullFile_Legacy(t *testing.T) {
  function Test_Template_resolve_FullLocale_ShortFile_Mixed (line 390) | func Test_Template_resolve_FullLocale_ShortFile_Mixed(t *testing.T) {
  function Test_Template_resolve_LangOnly_FullFile_Mixed (line 415) | func Test_Template_resolve_LangOnly_FullFile_Mixed(t *testing.T) {
  function Test_Template_extsAndBase (line 440) | func Test_Template_extsAndBase(t *testing.T) {

FILE: render/xml.go
  type xmlRenderer (line 8) | type xmlRenderer struct
    method ContentType (line 12) | func (s xmlRenderer) ContentType() string {
    method Render (line 16) | func (s xmlRenderer) Render(w io.Writer, data Data) error {
  function XML (line 25) | func XML(v any) Renderer {
  method XML (line 31) | func (e *Engine) XML(v any) Renderer {

FILE: render/xml_test.go
  function Test_XML (line 11) | func Test_XML(t *testing.T) {

FILE: request_data.go
  type requestData (line 5) | type requestData struct
  function newRequestData (line 10) | func newRequestData() *requestData {

FILE: request_data_test.go
  function Test_newRequestData (line 9) | func Test_newRequestData(t *testing.T) {

FILE: request_logger.go
  function randString (line 17) | func randString(i int) (string, error) {
  function formatBytes (line 27) | func formatBytes(b uint64) string {
  function RequestLoggerFunc (line 45) | func RequestLoggerFunc(h Handler) Handler {

FILE: resource.go
  type Resource (line 28) | type Resource interface
  type Middler (line 38) | type Middler interface
  type BaseResource (line 57) | type BaseResource struct
    method List (line 60) | func (v BaseResource) List(c Context) error {
    method Show (line 65) | func (v BaseResource) Show(c Context) error {
    method Create (line 70) | func (v BaseResource) Create(c Context) error {
    method Update (line 75) | func (v BaseResource) Update(c Context) error {
    method Destroy (line 80) | func (v BaseResource) Destroy(c Context) error {

FILE: response.go
  type Response (line 14) | type Response struct
    method WriteHeader (line 21) | func (w *Response) WriteHeader(code int) {
    method Write (line 36) | func (w *Response) Write(b []byte) (int, error) {
    method Hijack (line 42) | func (w *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
    method Flush (line 50) | func (w *Response) Flush() {
    method CloseNotify (line 61) | func (w *Response) CloseNotify() <-chan bool {
  type closeNotifier (line 56) | type closeNotifier interface

FILE: response_test.go
  function Test_Response_MultipleWrite (line 11) | func Test_Response_MultipleWrite(t *testing.T) {

FILE: route.go
  method Routes (line 13) | func (a *App) Routes() RouteList {
  function addExtraParamsTo (line 21) | func addExtraParamsTo(path string, opts map[string]any) string {
  type RouteHelperFunc (line 61) | type RouteHelperFunc
  type RouteList (line 66) | type RouteList
    method Len (line 75) | func (a RouteList) Len() int      { return len(a) }
    method Swap (line 76) | func (a RouteList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
    method Less (line 77) | func (a RouteList) Less(i, j int) bool {
    method Lookup (line 86) | func (a RouteList) Lookup(name string) (*RouteInfo, error) {

FILE: route_info.go
  type RouteInfo (line 20) | type RouteInfo struct
    method String (line 33) | func (ri RouteInfo) String() string {
    method Alias (line 40) | func (ri *RouteInfo) Alias(aliases ...string) *RouteInfo {
    method Name (line 49) | func (ri *RouteInfo) Name(name string) *RouteInfo {
    method BuildPathHelper (line 73) | func (ri *RouteInfo) BuildPathHelper() RouteHelperFunc {
    method ServeHTTP (line 94) | func (ri RouteInfo) ServeHTTP(res http.ResponseWriter, req *http.Reque...

FILE: route_info_test.go
  function Test_RouteInfo_ServeHTTP_SQL_Error (line 14) | func Test_RouteInfo_ServeHTTP_SQL_Error(t *testing.T) {

FILE: route_mappings.go
  constant AssetsAgeVarName (line 20) | AssetsAgeVarName = "ASSETS_MAX_AGE"
  method GET (line 26) | func (a *App) GET(p string, h Handler) *RouteInfo {
  method POST (line 31) | func (a *App) POST(p string, h Handler) *RouteInfo {
  method PUT (line 36) | func (a *App) PUT(p string, h Handler) *RouteInfo {
  method DELETE (line 41) | func (a *App) DELETE(p string, h Handler) *RouteInfo {
  method HEAD (line 46) | func (a *App) HEAD(p string, h Handler) *RouteInfo {
  method OPTIONS (line 51) | func (a *App) OPTIONS(p string, h Handler) *RouteInfo {
  method PATCH (line 56) | func (a *App) PATCH(p string, h Handler) *RouteInfo {
  method Redirect (line 61) | func (a *App) Redirect(status int, from, to string) *RouteInfo {
  method Mount (line 83) | func (a *App) Mount(p string, h http.Handler) {
  method ServeFiles (line 94) | func (a *App) ServeFiles(p string, root http.FileSystem) {
  method fileServer (line 102) | func (a *App) fileServer(fs http.FileSystem) http.Handler {
  type newable (line 126) | type newable interface
  type editable (line 130) | type editable interface
  method Resource (line 158) | func (a *App) Resource(p string, r Resource) *App {
  method ANY (line 224) | func (a *App) ANY(p string, h Handler) {
  method Group (line 243) | func (a *App) Group(groupPath string) *App {
  method VirtualHost (line 284) | func (a *App) VirtualHost(h string) *App {
  method RouteHelpers (line 293) | func (a *App) RouteHelpers() map[string]RouteHelperFunc {
  method addRoute (line 302) | func (e *Home) addRoute(method string, url string, h Handler) *RouteInfo {
  function stripAsset (line 339) | func stripAsset(path string, h http.Handler, a *App) http.Handler {

FILE: route_mappings_test.go
  function Test_App_Routes_without_Root (line 9) | func Test_App_Routes_without_Root(t *testing.T) {
  function Test_App_Routes_with_Root (line 25) | func Test_App_Routes_with_Root(t *testing.T) {
  function Test_App_RouteName (line 44) | func Test_App_RouteName(t *testing.T) {
  function Test_RouteList_Lookup (line 64) | func Test_RouteList_Lookup(t *testing.T) {
  function Test_App_RouteHelpers (line 85) | func Test_App_RouteHelpers(t *testing.T) {
  type resourceHandler (line 113) | type resourceHandler struct
    method List (line 115) | func (r resourceHandler) List(Context) error {
    method Show (line 119) | func (r resourceHandler) Show(Context) error {
    method Create (line 123) | func (r resourceHandler) Create(Context) error {
    method Update (line 127) | func (r resourceHandler) Update(Context) error {
    method Destroy (line 131) | func (r resourceHandler) Destroy(Context) error {
  function Test_App_Routes_Resource (line 135) | func Test_App_Routes_Resource(t *testing.T) {
  function Test_App_VirtualHost (line 158) | func Test_App_VirtualHost(t *testing.T) {

FILE: routenamer.go
  type RouteNamer (line 13) | type RouteNamer interface
  type baseRouteNamer (line 20) | type baseRouteNamer struct
    method NameRoute (line 22) | func (drn baseRouteNamer) NameRoute(p string) string {

FILE: router_test.go
  function testApp (line 20) | func testApp() *App {
  function otherTestApp (line 51) | func otherTestApp() *App {
  function Test_MethodNotFoundError (line 63) | func Test_MethodNotFoundError(t *testing.T) {
  function Test_Mount_Buffalo (line 82) | func Test_Mount_Buffalo(t *testing.T) {
  function Test_Mount_Buffalo_on_Group (line 106) | func Test_Mount_Buffalo_on_Group(t *testing.T) {
  function muxer (line 131) | func muxer() http.Handler {
  function Test_Mount_Handler (line 142) | func Test_Mount_Handler(t *testing.T) {
  function Test_PreHandlers (line 166) | func Test_PreHandlers(t *testing.T) {
  function Test_PreWares (line 207) | func Test_PreWares(t *testing.T) {
  function Test_Router (line 252) | func Test_Router(t *testing.T) {
  function Test_Router_Group (line 277) | func Test_Router_Group(t *testing.T) {
  function Test_Router_Group_on_Group (line 291) | func Test_Router_Group_on_Group(t *testing.T) {
  function Test_Router_Group_Middleware (line 309) | func Test_Router_Group_Middleware(t *testing.T) {
  function Test_Router_Redirect (line 325) | func Test_Router_Redirect(t *testing.T) {
  function Test_Router_ServeFiles (line 333) | func Test_Router_ServeFiles(t *testing.T) {
  function Test_Router_InvalidURL (line 365) | func Test_Router_InvalidURL(t *testing.T) {
  type WebResource (line 387) | type WebResource struct
    method Edit (line 392) | func (v WebResource) Edit(c Context) error {
    method New (line 397) | func (v WebResource) New(c Context) error {
  function Test_App_NamedRoutes (line 401) | func Test_App_NamedRoutes(t *testing.T) {
  function Test_App_NamedRoutes_MissingParameter (line 476) | func Test_App_NamedRoutes_MissingParameter(t *testing.T) {
  function Test_Resource (line 501) | func Test_Resource(t *testing.T) {
  type paramKeyResource (line 571) | type paramKeyResource struct
    method ParamKey (line 575) | func (paramKeyResource) ParamKey() string {
  function Test_Resource_ParamKey (line 579) | func Test_Resource_ParamKey(t *testing.T) {
  type mwResource (line 592) | type mwResource struct
    method Use (line 596) | func (mwResource) Use() []MiddlewareFunc {
    method List (line 611) | func (m mwResource) List(c Context) error {
  function Test_Resource_MW (line 615) | func Test_Resource_MW(t *testing.T) {
  type userResource (line 632) | type userResource struct
    method List (line 634) | func (u *userResource) List(c Context) error {
    method Show (line 638) | func (u *userResource) Show(c Context) error {
    method New (line 642) | func (u *userResource) New(c Context) error {
    method Create (line 646) | func (u *userResource) Create(c Context) error {
    method Edit (line 650) | func (u *userResource) Edit(c Context) error {
    method Update (line 654) | func (u *userResource) Update(c Context) error {
    method Destroy (line 658) | func (u *userResource) Destroy(c Context) error {
  function Test_ResourceOnResource (line 662) | func Test_ResourceOnResource(t *testing.T) {
  function Test_buildRouteName (line 728) | func Test_buildRouteName(t *testing.T) {
  function Test_CatchAll_Route (line 767) | func Test_CatchAll_Route(t *testing.T) {
  function Test_Router_Matches_Trailing_Slash (line 783) | func Test_Router_Matches_Trailing_Slash(t *testing.T) {

FILE: runtime/build.go
  type BuildInfo (line 36) | type BuildInfo struct
    method String (line 42) | func (b BuildInfo) String() string {
  function Build (line 61) | func Build() BuildInfo {
  function loadBuildInfo (line 70) | func loadBuildInfo() BuildInfo {
  function SetBuild (line 111) | func SetBuild(b BuildInfo) {

FILE: server.go
  method Serve (line 22) | func (a *App) Serve(srvs ...servers.Server) error {
  method Stop (line 115) | func (a *App) Stop(err error) error {
  method ServeHTTP (line 130) | func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  method processPreHandlers (line 150) | func (a *App) processPreHandlers(res http.ResponseWriter, req *http.Requ...
  method normalizePath (line 177) | func (a *App) normalizePath(path string) string {

FILE: server_test.go
  constant waitStart (line 19) | waitStart   = 2
  constant waitRun (line 20) | waitRun     = 2
  constant consumerRun (line 21) | consumerRun = 8
  function startApp (line 26) | func startApp(app *App, wg *sync.WaitGroup, r *require.Assertions) {
  function Test_Server_Simple (line 36) | func Test_Server_Simple(t *testing.T) {
  function timeConsumer (line 55) | func timeConsumer(c Context) error {
  function Test_Server_GracefulShutdownOngoingRequest (line 64) | func Test_Server_GracefulShutdownOngoingRequest(t *testing.T) {
  function timerWorker (line 110) | func timerWorker(args worker.Args) error {
  function Test_Server_GracefulShutdownOngoingWorker (line 119) | func Test_Server_GracefulShutdownOngoingWorker(t *testing.T) {

FILE: servers/listener.go
  type Listener (line 11) | type Listener struct
    method SetAddr (line 17) | func (s *Listener) SetAddr(addr string) {
    method String (line 24) | func (s *Listener) String() string {
    method Start (line 29) | func (s *Listener) Start(c context.Context, h http.Handler) error {
  function UnixSocket (line 35) | func UnixSocket(addr string) (*Listener, error) {

FILE: servers/servers.go
  type Server (line 10) | type Server interface
  function Wrap (line 17) | func Wrap(s *http.Server) Server {
  function WrapTLS (line 23) | func WrapTLS(s *http.Server, certFile string, keyFile string) Server {
  function WrapListener (line 32) | func WrapListener(s *http.Server, l net.Listener) Server {

FILE: servers/simple.go
  type Simple (line 10) | type Simple struct
    method SetAddr (line 15) | func (s *Simple) SetAddr(addr string) {
    method String (line 22) | func (s *Simple) String() string {
    method Start (line 27) | func (s *Simple) Start(c context.Context, h http.Handler) error {
  function New (line 33) | func New() *Simple {

FILE: servers/tls.go
  type TLS (line 10) | type TLS struct
    method SetAddr (line 17) | func (s *TLS) SetAddr(addr string) {
    method String (line 24) | func (s *TLS) String() string {
    method Start (line 29) | func (s *TLS) Start(c context.Context, h http.Handler) error {

FILE: session.go
  type Session (line 11) | type Session struct
    method Save (line 18) | func (s *Session) Save() error {
    method Get (line 23) | func (s *Session) Get(name any) any {
    method GetOnce (line 28) | func (s *Session) GetOnce(name any) any {
    method Set (line 38) | func (s *Session) Set(name, value any) {
    method Delete (line 43) | func (s *Session) Delete(name any) {
    method Clear (line 48) | func (s *Session) Clear() {
  method getSession (line 55) | func (a *App) getSession(r *http.Request, w http.ResponseWriter) *Session {

FILE: session_test.go
  function Test_Session_SingleCookie (line 15) | func Test_Session_SingleCookie(t *testing.T) {
  function Test_Session_CustomValue (line 39) | func Test_Session_CustomValue(t *testing.T) {

FILE: worker/job.go
  type Args (line 6) | type Args
    method String (line 8) | func (a Args) String() string {
  type Job (line 14) | type Job struct
    method String (line 23) | func (j Job) String() string {

FILE: worker/simple.go
  function NewSimple (line 17) | func NewSimple() *Simple {
  function NewSimpleWithContext (line 26) | func NewSimpleWithContext(ctx context.Context) *Simple {
  type Simple (line 45) | type Simple struct
    method Register (line 56) | func (w *Simple) Register(name string, h Handler) error {
    method Start (line 71) | func (w *Simple) Start(ctx context.Context) error {
    method Stop (line 84) | func (w *Simple) Stop() error {
    method Perform (line 99) | func (w *Simple) Perform(job Job) error {
    method PerformAt (line 157) | func (w *Simple) PerformAt(job Job, t time.Time) error {
    method PerformIn (line 163) | func (w *Simple) PerformIn(job Job, d time.Duration) error {
  function safeRun (line 142) | func safeRun(fn func() error) (err error) {
  type SimpleLogger (line 195) | type SimpleLogger interface

FILE: worker/simple_test.go
  function sampleHandler (line 12) | func sampleHandler(Args) error {
  function Test_Simple_RegisterEmpty (line 16) | func Test_Simple_RegisterEmpty(t *testing.T) {
  function Test_Simple_RegisterNil (line 24) | func Test_Simple_RegisterNil(t *testing.T) {
  function Test_Simple_RegisterEmptyNil (line 32) | func Test_Simple_RegisterEmptyNil(t *testing.T) {
  function Test_Simple_RegisterExisting (line 40) | func Test_Simple_RegisterExisting(t *testing.T) {
  function Test_Simple_StartStop (line 51) | func Test_Simple_StartStop(t *testing.T) {
  function Test_Simple_Perform (line 67) | func Test_Simple_Perform(t *testing.T) {
  function Test_Simple_PerformBroken (line 87) | func Test_Simple_PerformBroken(t *testing.T) {
  function Test_Simple_PerformWithEmptyJob (line 110) | func Test_Simple_PerformWithEmptyJob(t *testing.T) {
  function Test_Simple_PerformWithUnknownJob (line 121) | func Test_Simple_PerformWithUnknownJob(t *testing.T) {
  function Test_Simple_PerformAfterStop (line 145) | func Test_Simple_PerformAfterStop(t *testing.T) {
  function Test_Simple_PerformAt (line 157) | func Test_Simple_PerformAt(t *testing.T) {
  function Test_Simple_PerformIn (line 184) | func Test_Simple_PerformIn(t *testing.T) {
  function Test_Simple_PerformInAfterStop (line 224) | func Test_Simple_PerformInAfterStop(t *testing.T) {

FILE: worker/worker.go
  type Handler (line 10) | type Handler
  type Worker (line 14) | type Worker interface

FILE: wrappers.go
  function WrapHandler (line 13) | func WrapHandler(h http.Handler) Handler {
  function WrapHandlerFunc (line 22) | func WrapHandlerFunc(h http.HandlerFunc) Handler {
  function WrapBuffaloHandler (line 33) | func WrapBuffaloHandler(h Handler) http.Handler {
  function WrapBuffaloHandlerFunc (line 44) | func WrapBuffaloHandlerFunc(h Handler) http.HandlerFunc {

FILE: wrappers_test.go
  function Test_WrapHandlerFunc (line 12) | func Test_WrapHandlerFunc(t *testing.T) {
  function Test_WrapHandler (line 26) | func Test_WrapHandler(t *testing.T) {
  function Test_WrapBuffaloHandler (line 40) | func Test_WrapBuffaloHandler(t *testing.T) {
  function Test_WrapBuffaloHandlerFunc (line 72) | func Test_WrapBuffaloHandlerFunc(t *testing.T) {
  function Benchmark_WrapBuffaloHandler (line 104) | func Benchmark_WrapBuffaloHandler(b *testing.B) {
Condensed preview — 177 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (419K chars).
[
  {
    "path": ".github/CODEOWNERS",
    "chars": 48,
    "preview": "# Default owner\n*       @gobuffalo/core-managers"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 82,
    "preview": "# These are supported funding model platforms\n\ngithub: markbates\npatreon: buffalo\n"
  },
  {
    "path": ".github/workflows/standard-go-test.yml",
    "chars": 606,
    "preview": "name: Standard Test\n\non:\n  push:\n    branches: [main v1]\n  pull_request:\n\npermissions:\n  contents: read\n\njobs:\n  call-st"
  },
  {
    "path": ".github/workflows/standard-stale.yml",
    "chars": 204,
    "preview": "name: Standard Autocloser\n\non:\n  schedule:\n    - cron: \"30 1 * * *\"\n\njobs:\n  call-standard-autocloser:\n    name: Autoclo"
  },
  {
    "path": ".gitignore",
    "chars": 269,
    "preview": "*.log\n.DS_Store\ndoc\ntmp\npkg\n*.gem\n*.pid\ncoverage\ncoverage.data\n*.pbxuser\n*.mode1v3\n.svn\nprofile\n.console_history\n.sass-c"
  },
  {
    "path": "BACKERS.md",
    "chars": 1043,
    "preview": "# Financial Backers of the Buffalo Project\n\nBuffalo is a community-driven project that is run by individuals who believe"
  },
  {
    "path": "Dockerfile",
    "chars": 266,
    "preview": "FROM gobuffalo/buffalo:latest\n\nARG CODECOV_TOKEN\n\nENV GOPROXY         https://proxy.golang.org\nENV BP              /src/"
  },
  {
    "path": "Dockerfile.build",
    "chars": 1337,
    "preview": "FROM golang:1.17\n\nEXPOSE 3000\n\nENV GOPROXY=https://proxy.golang.org\n\nRUN apt-get update \\\n    && apt-get install -y -q b"
  },
  {
    "path": "Dockerfile.slim.build",
    "chars": 774,
    "preview": "FROM golang:1.17-alpine\n\nEXPOSE 3000\n\nENV GOPROXY=https://proxy.golang.org \n\nRUN apk add --no-cache --upgrade apk-tools "
  },
  {
    "path": "LICENSE.txt",
    "chars": 1076,
    "preview": "The MIT License (MIT)\nCopyright (c) 2016 Mark Bates\n\nPermission is hereby granted, free of charge, to any person obtaini"
  },
  {
    "path": "README.md",
    "chars": 5744,
    "preview": "<p align=\"center\"><img src=\"https://raw.githubusercontent.com/gobuffalo/buffalo/master/logo.svg\" width=\"360\"></p>\n\n<p al"
  },
  {
    "path": "SECURITY.md",
    "chars": 252,
    "preview": "# Security Policy\n\n## Supported Versions\n\n| Version | Supported          |\n| ------- | ------------------ |\n| 1.x.x   | "
  },
  {
    "path": "SHOULDERS.md",
    "chars": 5651,
    "preview": "# Buffalo Stands on the Shoulders of Giants\n\nBuffalo does not try to reinvent the wheel! Instead, it uses the already gr"
  },
  {
    "path": "app.go",
    "chars": 2151,
    "preview": "package buffalo\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"sync\"\n\n\t\"github.com/gobuffalo/buffalo/internal/env\"\n\t\"github.com/gorilla/"
  },
  {
    "path": "app_test.go",
    "chars": 67,
    "preview": "package buffalo\n\nfunc voidHandler(c Context) error {\n\treturn nil\n}\n"
  },
  {
    "path": "binding/bindable.go",
    "chars": 221,
    "preview": "package binding\n\nimport \"net/http\"\n\n// Bindable when implemented, on a type\n// will override any Binders that have been\n"
  },
  {
    "path": "binding/bindable_test.go",
    "chars": 412,
    "preview": "package binding\n\nimport (\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\ntype or"
  },
  {
    "path": "binding/binding.go",
    "chars": 2543,
    "preview": "package binding\n\nimport (\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/gobuffalo/buffalo/binding/decoders\"\n\t\"github.com/gobuffalo/b"
  },
  {
    "path": "binding/binding_test.go",
    "chars": 1431,
    "preview": "package binding\n\nimport (\n\t\"net/http\"\n\t\"net/url\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\ntype blogPost str"
  },
  {
    "path": "binding/decoders/decoders.go",
    "chars": 826,
    "preview": "package decoders\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\nvar (\n\tlock = &sync.RWMutex{}\n\n\t// timeFormats are the base time formats s"
  },
  {
    "path": "binding/decoders/null_time.go",
    "chars": 770,
    "preview": "package decoders\n\nimport \"github.com/gobuffalo/buffalo/internal/nulls\"\n\n// NullTimeDecoderFn is a custom type decoder fu"
  },
  {
    "path": "binding/decoders/null_time_test.go",
    "chars": 1056,
    "preview": "package decoders\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/gobuffalo/buffalo/internal/nulls\"\n\t\"github.com/stretchr/test"
  },
  {
    "path": "binding/decoders/parse_time.go",
    "chars": 419,
    "preview": "package decoders\n\nimport (\n\t\"time\"\n)\n\nfunc parseTime(vals []string) (time.Time, error) {\n\tvar t time.Time\n\tvar err error"
  },
  {
    "path": "binding/decoders/time.go",
    "chars": 205,
    "preview": "package decoders\n\n// TimeDecoderFn is a custom type decoder func for Time fields\nfunc TimeDecoderFn() func([]string) (an"
  },
  {
    "path": "binding/decoders/time_test.go",
    "chars": 1135,
    "preview": "package decoders\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestParseTimeErrorParsing("
  },
  {
    "path": "binding/file.go",
    "chars": 348,
    "preview": "package binding\n\nimport (\n\t\"mime/multipart\"\n)\n\n// File holds information regarding an uploaded file\ntype File struct {\n\t"
  },
  {
    "path": "binding/file_request_type_binder.go",
    "chars": 1632,
    "preview": "package binding\n\nimport (\n\t\"net/http\"\n\t\"reflect\"\n\n\t\"github.com/monoculum/formam\"\n)\n\n// FileRequestTypeBinder is in charg"
  },
  {
    "path": "binding/file_test.go",
    "chars": 3648,
    "preview": "package binding_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"path/fil"
  },
  {
    "path": "binding/html_content_type_binder.go",
    "chars": 745,
    "preview": "package binding\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/monoculum/formam\"\n)\n\n// HTMLContentTypeBinder is in charge of bindin"
  },
  {
    "path": "binding/json_content_type_binder.go",
    "chars": 575,
    "preview": "package binding\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n)\n\n// JSONContentTypeBinder is in charge of binding JSON request "
  },
  {
    "path": "binding/request_binder.go",
    "chars": 1575,
    "preview": "package binding\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/gobuffalo/buffalo/internal/httpx"
  },
  {
    "path": "binding/request_binder_test.go",
    "chars": 1648,
    "preview": "package binding\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Te"
  },
  {
    "path": "binding/types.go",
    "chars": 491,
    "preview": "package binding\n\nimport (\n\t\"net/http\"\n)\n\n// ContenTypeBinder are those capable of handling a request type like JSON or X"
  },
  {
    "path": "binding/xml_request_type_binder.go",
    "chars": 560,
    "preview": "package binding\n\nimport (\n\t\"encoding/xml\"\n\t\"net/http\"\n)\n\n// XMLRequestTypeBinder is in charge of binding XML request typ"
  },
  {
    "path": "buffalo.go",
    "chars": 566,
    "preview": "/*\nPackage buffalo is a Go web development eco-system, designed to make your life easier.\n\nBuffalo helps you to generate"
  },
  {
    "path": "context.go",
    "chars": 2247,
    "preview": "package buffalo\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/gobuffalo/buffalo/binding\"\n\t\"github.com/gobuff"
  },
  {
    "path": "cookies.go",
    "chars": 2018,
    "preview": "package buffalo\n\nimport (\n\t\"net/http\"\n\t\"time\"\n)\n\n// Cookies allows you to easily get cookies from the request, and set c"
  },
  {
    "path": "cookies_test.go",
    "chars": 1652,
    "preview": "package buffalo\n\nimport (\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n"
  },
  {
    "path": "default_context.go",
    "chars": 7835,
    "preview": "package buffalo\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"maps\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"r"
  },
  {
    "path": "default_context_test.go",
    "chars": 8218,
    "preview": "package buffalo\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo/render\"\n"
  },
  {
    "path": "errors.go",
    "chars": 7308,
    "preview": "package buffalo\n\nimport (\n\t\"database/sql\"\n\t_ \"embed\"\n\t\"encoding/json\"\n\t\"encoding/xml\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"run"
  },
  {
    "path": "errors_test.go",
    "chars": 5730,
    "preview": "package buffalo\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/httptest\"\n\t\"github.com/gobuffalo/l"
  },
  {
    "path": "events.go",
    "chars": 2388,
    "preview": "package buffalo\n\n// TODO: TODO-v1 check if they are really need to be exported.\n/* The event id should be unique across "
  },
  {
    "path": "flash.go",
    "chars": 1304,
    "preview": "package buffalo\n\nimport \"encoding/json\"\n\n// flashKey is the prefix inside the Session.\nconst flashKey = \"_flash_\"\n\n// Fl"
  },
  {
    "path": "flash_test.go",
    "chars": 3313,
    "preview": "package buffalo\n\nimport (\n\t\"net/http\"\n\t\"testing\"\n\t\"text/template\"\n\n\t\"github.com/gobuffalo/buffalo/render\"\n\t\"github.com/g"
  },
  {
    "path": "fs.go",
    "chars": 2327,
    "preview": "package buffalo\n\nimport (\n\t\"fmt\"\n\t\"io/fs\"\n\t\"os\"\n)\n\n// FS wraps a directory and an embed FS that are expected to have the"
  },
  {
    "path": "fs_test.go",
    "chars": 2769,
    "preview": "package buffalo\n\nimport (\n\t\"io\"\n\t\"io/fs\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo/internal/testdata/embedded\"\n\t\"github"
  },
  {
    "path": "go.mod",
    "chars": 1978,
    "preview": "module github.com/gobuffalo/buffalo\n\ngo 1.25.0\n\nrequire (\n\tgithub.com/BurntSushi/toml v1.2.1\n\tgithub.com/gobuffalo/event"
  },
  {
    "path": "go.sum",
    "chars": 10803,
    "preview": "github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=\ngithub.com/BurntSushi/toml v1.2.1/go.m"
  },
  {
    "path": "handler.go",
    "chars": 684,
    "preview": "package buffalo\n\n// Handler is the basis for all of Buffalo. A Handler\n// will be given a Context interface that represe"
  },
  {
    "path": "home.go",
    "chars": 1426,
    "preview": "package buffalo\n\nimport (\n\t\"github.com/gorilla/mux\"\n)\n\n/* TODO: consider to split out Home (or Router, whatever) from Ap"
  },
  {
    "path": "internal/defaults/defaults.go",
    "chars": 411,
    "preview": "package defaults\n\nfunc String(s1, s2 string) string {\n\tif s1 == \"\" {\n\t\treturn s2\n\t}\n\treturn s1\n}\n\nfunc Int(i1, i2 int) i"
  },
  {
    "path": "internal/defaults/defaults_test.go",
    "chars": 918,
    "preview": "package defaults\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc Test_String(t *testing.T) {\n\ta := a"
  },
  {
    "path": "internal/env/env.go",
    "chars": 1827,
    "preview": "// Package env provides environment variable utilities for Buffalo.\n// This package replaces the github.com/gobuffalo/en"
  },
  {
    "path": "internal/fakesmtp/connection.go",
    "chars": 545,
    "preview": "package fakesmtp\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"net\"\n)\n\n// Connection of a client with our server\ntype Connection struct {\n"
  },
  {
    "path": "internal/fakesmtp/server.go",
    "chars": 2906,
    "preview": "package fakesmtp\n\n// This server is inspired by https://github.com/andrewarrow/jungle_smtp\n// and most of its functional"
  },
  {
    "path": "internal/httpx/content_type.go",
    "chars": 560,
    "preview": "package httpx\n\nimport (\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/gobuffalo/buffalo/internal/defaults\"\n)\n\nfunc ContentType(re"
  },
  {
    "path": "internal/httpx/content_type_test.go",
    "chars": 829,
    "preview": "package httpx\n\nimport (\n\t\"net/http/httptest\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test_ContentType"
  },
  {
    "path": "internal/meta/meta.go",
    "chars": 1121,
    "preview": "// Package meta provides application metadata for Buffalo's plugin system.\npackage meta\n\nimport (\n\t\"os\"\n\t\"path/filepath\""
  },
  {
    "path": "internal/meta/meta_test.go",
    "chars": 1590,
    "preview": "package meta\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test_New_Defaul"
  },
  {
    "path": "internal/nulls/nulls.go",
    "chars": 1913,
    "preview": "package nulls\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"time\"\n)\n\n// Time represents a time.Time that may be nu"
  },
  {
    "path": "internal/templates/error.dev.html",
    "chars": 14586,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=e"
  },
  {
    "path": "internal/templates/error.prod.html",
    "chars": 1587,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n    <style>\n        h1,\n        p.powered {\n            text-align: center\n        }\n\n    "
  },
  {
    "path": "internal/templates/notfound.prod.html",
    "chars": 1517,
    "preview": "<!DOCTYPE html>\n<html>\n\n<head>\n    <style>\n        h1,\n        p.powered {\n            text-align: center\n        }\n\n   "
  },
  {
    "path": "internal/testdata/disk/file.txt",
    "chars": 21,
    "preview": "This file is on disk."
  },
  {
    "path": "internal/testdata/disk/file2.txt",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "internal/testdata/disk/under/sub/subfile",
    "chars": 25,
    "preview": "This file is on disk/sub."
  },
  {
    "path": "internal/testdata/embedded/embed.go",
    "chars": 109,
    "preview": "package embedded\n\nimport (\n\t\"embed\"\n)\n\n//go:embed *\nvar files embed.FS\n\nfunc FS() embed.FS {\n\treturn files\n}\n"
  },
  {
    "path": "internal/testdata/embedded/file.txt",
    "chars": 22,
    "preview": "This file is embedded."
  },
  {
    "path": "internal/testdata/embedded/under/sub/subfile",
    "chars": 29,
    "preview": "This file is on embedded/sub."
  },
  {
    "path": "internal/testdata/panic.txt",
    "chars": 49,
    "preview": "This file must not be accessible from buffalo.FS."
  },
  {
    "path": "logger.go",
    "chars": 181,
    "preview": "package buffalo\n\nimport (\n\t\"github.com/gobuffalo/logger\"\n)\n\n// Logger interface is used throughout Buffalo\n// apps to lo"
  },
  {
    "path": "mail/README.md",
    "chars": 2884,
    "preview": "# github.com/gobuffalo/buffalo/mail\n\nThis package is intended to allow easy Email sending with Buffalo, it allows you to"
  },
  {
    "path": "mail/attachment.go",
    "chars": 186,
    "preview": "package mail\n\nimport \"io\"\n\n// Attachment are files added into a email message\ntype Attachment struct {\n\tName        stri"
  },
  {
    "path": "mail/body.go",
    "chars": 156,
    "preview": "package mail\n\n// Body represents one of the bodies in the Message could be main or alternative\ntype Body struct {\n\tConte"
  },
  {
    "path": "mail/dialer.go",
    "chars": 5789,
    "preview": "// Portions of this code are derived from the go-mail/mail project.\n// https://github.com/go-mail/mail (MIT License)\n\npa"
  },
  {
    "path": "mail/mail.go",
    "chars": 1294,
    "preview": "// Package mail provides email sending functionality for Buffalo applications.\n// It supports SMTP delivery with customi"
  },
  {
    "path": "mail/mail_test.go",
    "chars": 838,
    "preview": "package mail\n\nimport (\n\t\"html/template\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo\"\n\t\"github.com/gobuffalo/b"
  },
  {
    "path": "mail/message.go",
    "chars": 2160,
    "preview": "package mail\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"io\"\n\t\"maps\"\n\t\"sync\"\n\n\t\"github.com/gobuffalo/buffalo/render\"\n)\n\n// Message r"
  },
  {
    "path": "mail/sender.go",
    "chars": 498,
    "preview": "package mail\n\n// Sender defines the interface for sending individual email messages.\ntype Sender interface {\n\t// Send de"
  },
  {
    "path": "mail/smtp_auth.go",
    "chars": 1051,
    "preview": "// Portions of this code are derived from the go-mail/mail project.\n// https://github.com/go-mail/mail (MIT License)\n\npa"
  },
  {
    "path": "mail/smtp_errors.go",
    "chars": 523,
    "preview": "// Portions of this code are derived from the go-mail/mail project.\n// https://github.com/go-mail/mail (MIT License)\n\npa"
  },
  {
    "path": "mail/smtp_message.go",
    "chars": 4047,
    "preview": "// Portions of this code are derived from the go-mail/mail project.\n// https://github.com/go-mail/mail (MIT License)\n\npa"
  },
  {
    "path": "mail/smtp_mime.go",
    "chars": 416,
    "preview": "// Portions of this code are derived from the go-mail/mail project.\n// https://github.com/go-mail/mail (MIT License)\n\npa"
  },
  {
    "path": "mail/smtp_send.go",
    "chars": 1831,
    "preview": "// Portions of this code are derived from the go-mail/mail project.\n// https://github.com/go-mail/mail (MIT License)\n\npa"
  },
  {
    "path": "mail/smtp_sender.go",
    "chars": 2573,
    "preview": "package mail\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"strconv\"\n)\n\n// SMTPSender delivers emails via an SMTP server.\ntype SMTPSender stru"
  },
  {
    "path": "mail/smtp_sender_test.go",
    "chars": 2259,
    "preview": "package mail_test\n\nimport (\n\t\"bytes\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo/internal/fakesmtp\"\n\t\"github.com/gobuffal"
  },
  {
    "path": "mail/smtp_writeto.go",
    "chars": 6193,
    "preview": "// Portions of this code are derived from the go-mail/mail project.\n// https://github.com/go-mail/mail (MIT License)\n\npa"
  },
  {
    "path": "method_override.go",
    "chars": 658,
    "preview": "package buffalo\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gobuffalo/buffalo/internal/defaults\"\n)\n\n// MethodOverride is the def"
  },
  {
    "path": "method_override_test.go",
    "chars": 529,
    "preview": "package buffalo\n\nimport (\n\t\"net/http\"\n\t\"net/url\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo/render\"\n\t\"github.com/gobuffa"
  },
  {
    "path": "middleware.go",
    "chars": 5445,
    "preview": "package buffalo\n\nimport (\n\t\"maps\"\n\t\"net/http\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strings\"\n\t\"sync\"\n)\n\n// MiddlewareFunc defines the "
  },
  {
    "path": "middleware_test.go",
    "chars": 6525,
    "preview": "package buffalo\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo/render\"\n\t\"github.com/gobuffalo/h"
  },
  {
    "path": "not_found_test.go",
    "chars": 1399,
    "preview": "package buffalo\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/httptest\"\n\t\"github.com/stretch"
  },
  {
    "path": "options.go",
    "chars": 5129,
    "preview": "package buffalo\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/gobuffalo/buffalo/internal/defaults\"\n\t\""
  },
  {
    "path": "options_test.go",
    "chars": 1440,
    "preview": "package buffalo\n\nimport (\n\t\"net/http\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo/internal/env\"\n\t\"github.com/s"
  },
  {
    "path": "plugins/cache.go",
    "chars": 1715,
    "preview": "package plugins\n\nimport (\n\t\"crypto/sha256\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/user\"\n\t\"path/filepath\"\n\t\"sync\"\n\n\t\"gi"
  },
  {
    "path": "plugins/command.go",
    "chars": 639,
    "preview": "package plugins\n\n// Command that the plugin supplies\ntype Command struct {\n\t// Name \"foo\"\n\tName string `json:\"name\"`\n\t//"
  },
  {
    "path": "plugins/decorate.go",
    "chars": 1918,
    "preview": "package plugins\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\n\t\"github.com/gobuffalo/buffalo"
  },
  {
    "path": "plugins/events.go",
    "chars": 180,
    "preview": "package plugins\n\nconst (\n\tEvtSetupStarted  = \"buffalo-plugins:setup:started\"\n\tEvtSetupErr      = \"buffalo-plugins:setup:"
  },
  {
    "path": "plugins/log.go",
    "chars": 95,
    "preview": "//go:build !debug\n\npackage plugins\n\nfunc log(_ string, fn func() error) error {\n\treturn fn()\n}\n"
  },
  {
    "path": "plugins/log_debug.go",
    "chars": 193,
    "preview": "//go:build debug\n\npackage plugins\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc log(name string, fn func() error) error {\n\tstart := t"
  },
  {
    "path": "plugins/plugcmds/available.go",
    "chars": 3710,
    "preview": "package plugcmds\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\n\t\"github.com/gobuffalo/buffalo/plugins\"\n\t\"github.com/gob"
  },
  {
    "path": "plugins/plugcmds/available_test.go",
    "chars": 1041,
    "preview": "package plugcmds\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/events\"\n\t\"github.com/spf13/cobra\"\n\t\"gi"
  },
  {
    "path": "plugins/plugcmds/plug_map.go",
    "chars": 1607,
    "preview": "//go:generate mapgen -name \"plug\" -zero \"plug{}\" -go-type \"plug\" -pkg \"\" -a \"nil\" -b \"nil\" -c \"nil\" -bb \"nil\" -destinati"
  },
  {
    "path": "plugins/plugcmds/plug_map_test.go",
    "chars": 848,
    "preview": "// Code generated by github.com/gobuffalo/mapgen. DO NOT EDIT.\n\npackage plugcmds\n\nimport (\n\t\"slices\"\n\t\"testing\"\n\n\t\"githu"
  },
  {
    "path": "plugins/plugdeps/command.go",
    "chars": 436,
    "preview": "package plugdeps\n\nimport \"encoding/json\"\n\n// Command is the plugin command you want to control further\ntype Command stru"
  },
  {
    "path": "plugins/plugdeps/plugdeps.go",
    "chars": 2065,
    "preview": "package plugdeps\n\nimport (\n\t\"fmt\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/gobuffalo/buffalo/internal/me"
  },
  {
    "path": "plugins/plugdeps/plugdeps_test.go",
    "chars": 1471,
    "preview": "package plugdeps\n\nimport (\n\t\"errors\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo/internal/meta\"\n\t\""
  },
  {
    "path": "plugins/plugdeps/plugin.go",
    "chars": 719,
    "preview": "package plugdeps\n\nimport (\n\t\"encoding/json\"\n\n\t\"github.com/gobuffalo/buffalo/internal/meta\"\n)\n\n// Plugin represents a Go "
  },
  {
    "path": "plugins/plugdeps/plugin_test.go",
    "chars": 17,
    "preview": "package plugdeps\n"
  },
  {
    "path": "plugins/plugdeps/plugins.go",
    "chars": 1805,
    "preview": "package plugdeps\n\nimport (\n\t\"io\"\n\t\"sort\"\n\t\"sync\"\n\n\t\"github.com/BurntSushi/toml\"\n)\n\n// Plugins manages the config/buffalo"
  },
  {
    "path": "plugins/plugdeps/plugins_test.go",
    "chars": 878,
    "preview": "package plugdeps\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test_Pl"
  },
  {
    "path": "plugins/plugdeps/pop.go",
    "chars": 110,
    "preview": "package plugdeps\n\nvar pop = Plugin{\n\tBinary: \"buffalo-pop\",\n\tGoGet:  \"github.com/gobuffalo/buffalo-pop/v2\",\n}\n"
  },
  {
    "path": "plugins/plugins.go",
    "chars": 5171,
    "preview": "package plugins\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io/fs\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"st"
  },
  {
    "path": "plugins/plugins_test.go",
    "chars": 1195,
    "preview": "package plugins\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/gobuffalo/buffalo/internal/env\"\n\t"
  },
  {
    "path": "plugins.go",
    "chars": 1307,
    "preview": "package buffalo\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/gobuffalo/buffalo/in"
  },
  {
    "path": "render/auto.go",
    "chars": 5001,
    "preview": "package render\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"path\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/gobuf"
  },
  {
    "path": "render/auto_test.go",
    "chars": 11030,
    "preview": "package render_test\n\nimport (\n\t\"net/http\"\n\t\"strings\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"github.com/gobuffalo/buffalo\"\n\t\"git"
  },
  {
    "path": "render/download.go",
    "chars": 2600,
    "preview": "package render\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime\"\n\t\"net/http\"\n\t\"path/filepath\"\n\t\"strconv\"\n)\n\ntype downloadRendere"
  },
  {
    "path": "render/download_test.go",
    "chars": 1841,
    "preview": "package render\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/"
  },
  {
    "path": "render/func.go",
    "chars": 1126,
    "preview": "package render\n\nimport \"io\"\n\n// RendererFunc is the interface for the the function\n// needed by the Func renderer.\ntype "
  },
  {
    "path": "render/func_test.go",
    "chars": 528,
    "preview": "package render\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test_Func(t *testing."
  },
  {
    "path": "render/helpers.go",
    "chars": 726,
    "preview": "package render\n\nimport (\n\t\"html/template\"\n\t\"net/http\"\n\n\t\"github.com/gobuffalo/helpers/forms\"\n\t\"github.com/gobuffalo/help"
  },
  {
    "path": "render/html.go",
    "chars": 2018,
    "preview": "package render\n\nimport (\n\t\"html\"\n\t\"strings\"\n\n\t\"github.com/gobuffalo/github_flavored_markdown\"\n\t\"github.com/gobuffalo/plu"
  },
  {
    "path": "render/html_test.go",
    "chars": 2516,
    "preview": "package render\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\ncon"
  },
  {
    "path": "render/js.go",
    "chars": 1235,
    "preview": "package render\n\n// JavaScript renders the named files using the 'application/javascript'\n// content type and the github."
  },
  {
    "path": "render/js_test.go",
    "chars": 3833,
    "preview": "package render\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\ncon"
  },
  {
    "path": "render/json.go",
    "chars": 553,
    "preview": "package render\n\nimport (\n\t\"encoding/json\"\n\t\"io\"\n)\n\ntype jsonRenderer struct {\n\tvalue any\n}\n\nfunc (s jsonRenderer) Conten"
  },
  {
    "path": "render/json_test.go",
    "chars": 391,
    "preview": "package render\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test_JSON(t *tes"
  },
  {
    "path": "render/markdown_test.go",
    "chars": 1147,
    "preview": "package render\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\ncon"
  },
  {
    "path": "render/options.go",
    "chars": 1331,
    "preview": "package render\n\nimport (\n\t\"io/fs\"\n\n\t\"github.com/gobuffalo/plush/v5/helpers/hctx\"\n)\n\n// Helpers to be included in all tem"
  },
  {
    "path": "render/partials_test.go",
    "chars": 5854,
    "preview": "package render\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfun"
  },
  {
    "path": "render/plain.go",
    "chars": 947,
    "preview": "package render\n\n// Plain renders the named files using the 'text/html'\n// content type and the github.com/gobuffalo/plus"
  },
  {
    "path": "render/plain_test.go",
    "chars": 586,
    "preview": "package render\n\nimport (\n\t\"bytes\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test_Plai"
  },
  {
    "path": "render/render.go",
    "chars": 1878,
    "preview": "package render\n\nimport (\n\t\"github.com/gobuffalo/helpers\"\n\t\"github.com/gobuffalo/helpers/forms\"\n\t\"github.com/gobuffalo/he"
  },
  {
    "path": "render/render_test.go",
    "chars": 491,
    "preview": "package render\n\nimport (\n\t\"os\"\n\t\"testing\"\n\t\"testing/fstest\"\n)\n\ntype Widget struct {\n\tName string\n}\n\nfunc (w Widget) ToPa"
  },
  {
    "path": "render/renderer.go",
    "chars": 304,
    "preview": "package render\n\nimport \"io\"\n\n// Renderer interface that must be satisfied to be used with\n// buffalo.Context.Render\ntype"
  },
  {
    "path": "render/sse.go",
    "chars": 1770,
    "preview": "package render\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n)\n\ntype sse struct {\n\tData any    `json:\"data\"`\n\tType strin"
  },
  {
    "path": "render/string.go",
    "chars": 1024,
    "preview": "package render\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype stringRenderer struct {\n\t*Engine\n\tbody string\n}\n\nfunc (s stringRenderer) C"
  },
  {
    "path": "render/string_map.go",
    "chars": 1538,
    "preview": "package render\n\nimport (\n\t\"slices\"\n\t\"sync\"\n)\n\n// stringMap wraps sync.Map and uses the following types:\n// key:   string"
  },
  {
    "path": "render/string_map_test.go",
    "chars": 738,
    "preview": "package render\n\nimport (\n\t\"slices\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test_stringMap(t *testing."
  },
  {
    "path": "render/string_test.go",
    "chars": 522,
    "preview": "package render_test\n\nimport (\n\t\"bytes\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo/render\"\n\t\"github.com/stretchr/testify/"
  },
  {
    "path": "render/template.go",
    "chars": 8899,
    "preview": "package render\n\nimport (\n\t\"fmt\"\n\t\"html/template\"\n\t\"io\"\n\t\"io/fs\"\n\t\"maps\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync"
  },
  {
    "path": "render/template_engine.go",
    "chars": 614,
    "preview": "package render\n\nimport (\n\t\"bytes\"\n\t\"html/template\"\n)\n\n// TemplateEngine needs to be implemented for a template system to"
  },
  {
    "path": "render/template_helpers.go",
    "chars": 1361,
    "preview": "package render\n\nimport (\n\t\"encoding/json\"\n\t\"html/template\"\n\t\"io\"\n\t\"path\"\n\t\"path/filepath\"\n\n\tht \"github.com/gobuffalo/hel"
  },
  {
    "path": "render/template_helpers_test.go",
    "chars": 2347,
    "preview": "package render\n\nimport (\n\t\"fmt\"\n\t\"html/template\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"github.com/gobuffalo/tags/v3\"\n\t\"github."
  },
  {
    "path": "render/template_test.go",
    "chars": 13049,
    "preview": "package render\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfun"
  },
  {
    "path": "render/xml.go",
    "chars": 604,
    "preview": "package render\n\nimport (\n\t\"encoding/xml\"\n\t\"io\"\n)\n\ntype xmlRenderer struct {\n\tvalue any\n}\n\nfunc (s xmlRenderer) ContentTy"
  },
  {
    "path": "render/xml_test.go",
    "chars": 485,
    "preview": "package render\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test_XML(t *test"
  },
  {
    "path": "request_data.go",
    "chars": 221,
    "preview": "package buffalo\n\nimport \"sync\"\n\ntype requestData struct {\n\td    map[string]any\n\tmoot *sync.RWMutex\n}\n\nfunc newRequestDat"
  },
  {
    "path": "request_data_test.go",
    "chars": 218,
    "preview": "package buffalo\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test_newRequestData(t *testing.T) {"
  },
  {
    "path": "request_logger.go",
    "chars": 2133,
    "preview": "package buffalo\n\nimport (\n\t\"crypto/rand\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/gobuffalo/buffalo/inte"
  },
  {
    "path": "resource.go",
    "chars": 2304,
    "preview": "package buffalo\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\n// Resource interface allows for the easy mapping\n// of common RESTful a"
  },
  {
    "path": "response.go",
    "chars": 1478,
    "preview": "package buffalo\n\nimport (\n\t\"bufio\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n)\n\n// Response implements the http.Respo"
  },
  {
    "path": "response_test.go",
    "chars": 383,
    "preview": "package buffalo\n\nimport (\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Te"
  },
  {
    "path": "route.go",
    "chars": 2184,
    "preview": "package buffalo\n\nimport (\n\t\"fmt\"\n\t\"html/template\"\n\t\"net/url\"\n\t\"slices\"\n\t\"strings\"\n)\n\n// Routes returns a list of all of "
  },
  {
    "path": "route_info.go",
    "chars": 2908,
    "preview": "package buffalo\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"net/http\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github"
  },
  {
    "path": "route_info_test.go",
    "chars": 1081,
    "preview": "package buffalo\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo/render\"\n\t\"github"
  },
  {
    "path": "route_mappings.go",
    "chars": 10559,
    "preview": "package buffalo\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\t\"path\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/gobu"
  },
  {
    "path": "route_mappings_test.go",
    "chars": 3849,
    "preview": "package buffalo\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test_App_Routes_without_Root(t *tes"
  },
  {
    "path": "routenamer.go",
    "chars": 1590,
    "preview": "package buffalo\n\nimport (\n\t\"strings\"\n\n\t\"github.com/gobuffalo/flect\"\n\t\"github.com/gobuffalo/flect/name\"\n)\n\n// RouteNamer "
  },
  {
    "path": "router_test.go",
    "chars": 19368,
    "preview": "package buffalo\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"path\"\n\t\"strings\"\n\t\"testing\"\n\t\"testing/fstest\"\n\n\t\"github.com/g"
  },
  {
    "path": "runtime/build.go",
    "chars": 3174,
    "preview": "// Deprecated: This package is deprecated and will be removed in a future version.\n// Use runtime/debug.ReadBuildInfo() "
  },
  {
    "path": "server.go",
    "chars": 4457,
    "preview": "package buffalo\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strings\"\n\t\"sync\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"g"
  },
  {
    "path": "server_test.go",
    "chars": 3909,
    "preview": "package buffalo\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/gobuffalo/buffalo/render\"\n\t\"github"
  },
  {
    "path": "servers/listener.go",
    "chars": 895,
    "preview": "package servers\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n)\n\n// Listener server for using a pre-defined net.Listene"
  },
  {
    "path": "servers/servers.go",
    "chars": 785,
    "preview": "package servers\n\nimport (\n\t\"context\"\n\t\"net\"\n\t\"net/http\"\n)\n\n// Server allows for custom server implementations\ntype Serve"
  },
  {
    "path": "servers/simple.go",
    "chars": 654,
    "preview": "package servers\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n)\n\n// Simple server\ntype Simple struct {\n\t*http.Server\n}\n\n// Set"
  },
  {
    "path": "servers/tls.go",
    "chars": 598,
    "preview": "package servers\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n)\n\n// TLS server\ntype TLS struct {\n\t*http.Server\n\tCertFile strin"
  },
  {
    "path": "session.go",
    "chars": 1437,
    "preview": "package buffalo\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gorilla/sessions\"\n)\n\n// Session wraps the \"github.com/gorilla/sessio"
  },
  {
    "path": "session_test.go",
    "chars": 1506,
    "preview": "package buffalo\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo/render\"\n\t\"github.com/"
  },
  {
    "path": "worker/job.go",
    "chars": 497,
    "preview": "package worker\n\nimport \"encoding/json\"\n\n// Args are the arguments passed into a job\ntype Args map[string]any\n\nfunc (a Ar"
  },
  {
    "path": "worker/simple.go",
    "chars": 4694,
    "preview": "package worker\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/sirupsen/logrus\"\n)\n\nvar _ Worker = &S"
  },
  {
    "path": "worker/simple_test.go",
    "chars": 4840,
    "preview": "package worker\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc sampleHan"
  },
  {
    "path": "worker/worker.go",
    "chars": 1328,
    "preview": "package worker\n\nimport (\n\t\"context\"\n\t\"time\"\n)\n\n// Handler function that will be run by the worker and given\n// a slice o"
  },
  {
    "path": "wrappers.go",
    "chars": 2554,
    "preview": "package buffalo\n\nimport (\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/gobuffalo/buffalo/internal/httpx\"\n\t\"github.com/gorilla/mu"
  },
  {
    "path": "wrappers_test.go",
    "chars": 2489,
    "preview": "package buffalo\n\nimport (\n\t\"net/http\"\n\t\"testing\"\n\n\t\"github.com/gobuffalo/buffalo/render\"\n\t\"github.com/gobuffalo/httptest"
  }
]

About this extraction

This page contains the full source code of the gobuffalo/buffalo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 177 files (366.3 KB), approximately 109.8k tokens, and a symbol index with 849 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!