├── .editorconfig ├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── FUNDING.yml ├── SECURITY.md ├── dependabot.yml └── workflows │ ├── ci.yml │ ├── cross-build.yml │ ├── lint.yml │ ├── release.yml │ └── release_published.yml ├── .gitignore ├── .golangci.yml ├── .goreleaser.yml ├── AUTHORS ├── LICENSE ├── README.md ├── admin.go ├── admin_test.go ├── caddy.go ├── caddy_test.go ├── caddyconfig ├── caddyfile │ ├── adapter.go │ ├── dispenser.go │ ├── dispenser_test.go │ ├── formatter.go │ ├── formatter_fuzz.go │ ├── formatter_test.go │ ├── importargs.go │ ├── importgraph.go │ ├── lexer.go │ ├── lexer_fuzz.go │ ├── lexer_test.go │ ├── parse.go │ ├── parse_test.go │ └── testdata │ │ ├── empty.txt │ │ ├── glob │ │ ├── .dotfile.txt │ │ └── import_test1.txt │ │ ├── import_args0.txt │ │ ├── import_args1.txt │ │ ├── import_glob0.txt │ │ ├── import_glob1.txt │ │ ├── import_glob2.txt │ │ ├── import_recursive0.txt │ │ ├── import_recursive1.txt │ │ ├── import_recursive2.txt │ │ ├── import_recursive3.txt │ │ ├── import_test1.txt │ │ ├── import_test2.txt │ │ └── only_white_space.txt ├── configadapters.go ├── httpcaddyfile │ ├── addresses.go │ ├── addresses_fuzz.go │ ├── addresses_test.go │ ├── builtins.go │ ├── builtins_test.go │ ├── directives.go │ ├── directives_test.go │ ├── httptype.go │ ├── httptype_test.go │ ├── options.go │ ├── options_test.go │ ├── pkiapp.go │ ├── serveroptions.go │ ├── shorthands.go │ ├── testdata │ │ ├── import_variadic.txt │ │ ├── import_variadic_snippet.txt │ │ └── import_variadic_with_import.txt │ ├── tlsapp.go │ └── tlsapp_test.go ├── httploader.go └── load.go ├── caddytest ├── a.caddy.localhost.crt ├── a.caddy.localhost.key ├── caddy.ca.cer ├── caddy.localhost.crt ├── caddy.localhost.key ├── caddytest.go ├── caddytest_test.go ├── integration │ ├── acme_test.go │ ├── acmeserver_test.go │ ├── autohttps_test.go │ ├── caddyfile_adapt │ │ ├── acme_server_custom_challenges.caddyfiletest │ │ ├── acme_server_default_challenges.caddyfiletest │ │ ├── acme_server_lifetime.caddyfiletest │ │ ├── acme_server_multi_custom_challenges.caddyfiletest │ │ ├── acme_server_policy-allow.caddyfiletest │ │ ├── acme_server_policy-both.caddyfiletest │ │ ├── acme_server_policy-deny.caddyfiletest │ │ ├── acme_server_sign_with_root.caddyfiletest │ │ ├── auto_https_disable_redirects.caddyfiletest │ │ ├── auto_https_ignore_loaded_certs.caddyfiletest │ │ ├── auto_https_off.caddyfiletest │ │ ├── bind_fd_fdgram_h123.caddyfiletest │ │ ├── bind_ipv6.caddyfiletest │ │ ├── enable_tls_for_catch_all_site.caddyfiletest │ │ ├── encode_options.caddyfiletest │ │ ├── error_example.caddyfiletest │ │ ├── error_multi_site_blocks.caddyfiletest │ │ ├── error_range_codes.caddyfiletest │ │ ├── error_range_simple_codes.caddyfiletest │ │ ├── error_simple_codes.caddyfiletest │ │ ├── error_sort.caddyfiletest │ │ ├── expression_quotes.caddyfiletest │ │ ├── file_server_disable_canonical_uris.caddyfiletest │ │ ├── file_server_etag_file_extensions.caddyfiletest │ │ ├── file_server_file_limit.caddyfiletest │ │ ├── file_server_pass_thru.caddyfiletest │ │ ├── file_server_precompressed.caddyfiletest │ │ ├── file_server_sort.caddyfiletest │ │ ├── file_server_status.caddyfiletest │ │ ├── forward_auth_authelia.caddyfiletest │ │ ├── forward_auth_rename_headers.caddyfiletest │ │ ├── global_options.caddyfiletest │ │ ├── global_options_acme.caddyfiletest │ │ ├── global_options_admin.caddyfiletest │ │ ├── global_options_admin_with_persist_config_off.caddyfiletest │ │ ├── global_options_debug_with_access_log.caddyfiletest │ │ ├── global_options_default_bind.caddyfiletest │ │ ├── global_options_log_and_site.caddyfiletest │ │ ├── global_options_log_basic.caddyfiletest │ │ ├── global_options_log_custom.caddyfiletest │ │ ├── global_options_log_multi.caddyfiletest │ │ ├── global_options_log_sampling.caddyfiletest │ │ ├── global_options_persist_config.caddyfiletest │ │ ├── global_options_preferred_chains.caddyfiletest │ │ ├── global_options_skip_install_trust.caddyfiletest │ │ ├── global_server_options_multi.caddyfiletest │ │ ├── global_server_options_single.caddyfiletest │ │ ├── handle_nested_in_route.caddyfiletest │ │ ├── handle_path.caddyfiletest │ │ ├── handle_path_sorting.caddyfiletest │ │ ├── header.caddyfiletest │ │ ├── heredoc.caddyfiletest │ │ ├── http_only_hostnames.caddyfiletest │ │ ├── http_only_on_any_address.caddyfiletest │ │ ├── http_only_on_domain.caddyfiletest │ │ ├── http_only_on_hostless_block.caddyfiletest │ │ ├── http_only_on_localhost.caddyfiletest │ │ ├── http_only_on_non_standard_port.caddyfiletest │ │ ├── http_valid_directive_like_site_address.caddyfiletest │ │ ├── https_on_domain.caddyfiletest │ │ ├── import_args_file.caddyfiletest │ │ ├── import_args_snippet.caddyfiletest │ │ ├── import_args_snippet_env_placeholder.caddyfiletest │ │ ├── import_block_snippet.caddyfiletest │ │ ├── import_block_snippet_args.caddyfiletest │ │ ├── import_blocks_snippet.caddyfiletest │ │ ├── import_blocks_snippet_nested.caddyfiletest │ │ ├── intercept_response.caddyfiletest │ │ ├── invoke_named_routes.caddyfiletest │ │ ├── log_add.caddyfiletest │ │ ├── log_append_encoder.caddyfiletest │ │ ├── log_except_catchall_blocks.caddyfiletest │ │ ├── log_filter_no_wrap.caddyfiletest │ │ ├── log_filter_with_header.txt │ │ ├── log_filters.caddyfiletest │ │ ├── log_multi_logger_name.caddyfiletest │ │ ├── log_override_hostname.caddyfiletest │ │ ├── log_override_name_multiaccess.caddyfiletest │ │ ├── log_override_name_multiaccess_debug.caddyfiletest │ │ ├── log_roll_days.caddyfiletest │ │ ├── log_sampling.caddyfiletest │ │ ├── log_skip_hosts.caddyfiletest │ │ ├── map_and_vars_with_raw_types.caddyfiletest │ │ ├── matcher_syntax.caddyfiletest │ │ ├── matchers_in_route.caddyfiletest │ │ ├── method_directive.caddyfiletest │ │ ├── metrics_disable_om.caddyfiletest │ │ ├── metrics_merge_options.caddyfiletest │ │ ├── metrics_perhost.caddyfiletest │ │ ├── metrics_syntax.caddyfiletest │ │ ├── not_block_merging.caddyfiletest │ │ ├── php_fastcgi_expanded_form.caddyfiletest │ │ ├── php_fastcgi_handle_response.caddyfiletest │ │ ├── php_fastcgi_index_off.caddyfiletest │ │ ├── php_fastcgi_matcher.caddyfiletest │ │ ├── php_fastcgi_subdirectives.caddyfiletest │ │ ├── php_fastcgi_try_files_override.caddyfiletest │ │ ├── php_fastcgi_try_files_override_no_dir_index.caddyfiletest │ │ ├── portless_upstream.caddyfiletest │ │ ├── push.caddyfiletest │ │ ├── replaceable_upstream.caddyfiletest │ │ ├── replaceable_upstream_partial_port.caddyfiletest │ │ ├── replaceable_upstream_port.caddyfiletest │ │ ├── request_body.caddyfiletest │ │ ├── request_header.caddyfiletest │ │ ├── reverse_proxy_buffers.caddyfiletest │ │ ├── reverse_proxy_dynamic_upstreams.caddyfiletest │ │ ├── reverse_proxy_dynamic_upstreams_grace_period.caddyfiletest │ │ ├── reverse_proxy_empty_non_http_transport.caddyfiletest │ │ ├── reverse_proxy_h2c_shorthand.caddyfiletest │ │ ├── reverse_proxy_handle_response.caddyfiletest │ │ ├── reverse_proxy_health_headers.caddyfiletest │ │ ├── reverse_proxy_health_method.caddyfiletest │ │ ├── reverse_proxy_health_path_query.caddyfiletest │ │ ├── reverse_proxy_health_reqbody.caddyfiletest │ │ ├── reverse_proxy_http_transport_forward_proxy_url.txt │ │ ├── reverse_proxy_http_transport_none_proxy.txt │ │ ├── reverse_proxy_http_transport_tls_file_cert.txt │ │ ├── reverse_proxy_http_transport_tls_inline_cert.txt │ │ ├── reverse_proxy_http_transport_url_proxy.txt │ │ ├── reverse_proxy_load_balance.caddyfiletest │ │ ├── reverse_proxy_load_balance_wrr.caddyfiletest │ │ ├── reverse_proxy_localaddr.caddyfiletest │ │ ├── reverse_proxy_options.caddyfiletest │ │ ├── reverse_proxy_port_range.caddyfiletest │ │ ├── reverse_proxy_trusted_proxies.caddyfiletest │ │ ├── reverse_proxy_upstream_placeholder.caddyfiletest │ │ ├── rewrite_directive_permutations.caddyfiletest │ │ ├── root_directive_permutations.caddyfiletest │ │ ├── server_names.caddyfiletest │ │ ├── shorthand_parameterized_placeholders.caddyfiletest │ │ ├── site_block_sorting.caddyfiletest │ │ ├── sort_directives_with_any_matcher_first.caddyfiletest │ │ ├── sort_directives_within_handle.caddyfiletest │ │ ├── sort_vars_in_reverse.caddyfiletest │ │ ├── tls_acme_preferred_chains.caddyfiletest │ │ ├── tls_automation_policies_1.caddyfiletest │ │ ├── tls_automation_policies_10.caddyfiletest │ │ ├── tls_automation_policies_11.caddyfiletest │ │ ├── tls_automation_policies_2.caddyfiletest │ │ ├── tls_automation_policies_3.caddyfiletest │ │ ├── tls_automation_policies_4.caddyfiletest │ │ ├── tls_automation_policies_5.caddyfiletest │ │ ├── tls_automation_policies_6.caddyfiletest │ │ ├── tls_automation_policies_7.caddyfiletest │ │ ├── tls_automation_policies_8.caddyfiletest │ │ ├── tls_automation_policies_9.caddyfiletest │ │ ├── tls_automation_policies_global_email_localhost.caddyfiletest │ │ ├── tls_automation_wildcard_force_automate.caddyfiletest │ │ ├── tls_automation_wildcard_shadowing.caddyfiletest │ │ ├── tls_client_auth_cert_file-legacy-with-verifier.caddyfiletest │ │ ├── tls_client_auth_cert_file-legacy.caddyfiletest │ │ ├── tls_client_auth_cert_file.caddyfiletest │ │ ├── tls_client_auth_inline_cert-legacy.caddyfiletest │ │ ├── tls_client_auth_inline_cert.caddyfiletest │ │ ├── tls_client_auth_inline_cert_with_leaf_trust.caddyfiletest │ │ ├── tls_conn_policy_consolidate.caddyfiletest │ │ ├── tls_dns_ttl.caddyfiletest │ │ ├── tls_explicit_issuer_dns_ttl.caddyfiletest │ │ ├── tls_explicit_issuer_propagation_options.caddyfiletest │ │ ├── tls_internal_options.caddyfiletest │ │ ├── tls_propagation_options.caddyfiletest │ │ ├── tracing.caddyfiletest │ │ ├── uri_query_operations.caddyfiletest │ │ ├── uri_replace_brace_escape.caddyfiletest │ │ └── wildcard_pattern.caddyfiletest │ ├── caddyfile_adapt_test.go │ ├── caddyfile_test.go │ ├── handler_test.go │ ├── intercept_test.go │ ├── leafcertloaders_test.go │ ├── listener_test.go │ ├── map_test.go │ ├── mockdns_test.go │ ├── pki_test.go │ ├── reverseproxy_test.go │ ├── sni_test.go │ ├── stream_test.go │ └── testdata │ │ ├── cookie.html │ │ ├── foo.txt │ │ ├── foo_with_multiple_trailing_newlines.txt │ │ ├── foo_with_trailing_newline.txt │ │ ├── import_respond.txt │ │ └── index.localhost.html └── leafcert.pem ├── cmd ├── caddy │ ├── main.go │ └── setcap.sh ├── cobra.go ├── commandfactory.go ├── commandfuncs.go ├── commands.go ├── main.go ├── main_test.go ├── packagesfuncs.go ├── removebinary.go ├── removebinary_windows.go ├── storagefuncs.go └── x509rootsfallback.go ├── context.go ├── context_test.go ├── duration_fuzz.go ├── filepath.go ├── filepath_windows.go ├── filesystem.go ├── go.mod ├── go.sum ├── internal ├── filesystems │ ├── map.go │ └── os.go ├── logs.go ├── metrics │ ├── metrics.go │ └── metrics_test.go ├── ranges.go ├── sockets.go └── testmocks │ └── dummyverifier.go ├── listen.go ├── listen_unix.go ├── listen_unix_setopt.go ├── listen_unix_setopt_freebsd.go ├── listeners.go ├── listeners_fuzz.go ├── listeners_test.go ├── logging.go ├── logging_test.go ├── metrics.go ├── modules.go ├── modules ├── caddyevents │ ├── app.go │ └── eventsconfig │ │ └── caddyfile.go ├── caddyfs │ └── filesystem.go ├── caddyhttp │ ├── app.go │ ├── autohttps.go │ ├── caddyauth │ │ ├── basicauth.go │ │ ├── caddyauth.go │ │ ├── caddyfile.go │ │ ├── command.go │ │ └── hashes.go │ ├── caddyhttp.go │ ├── caddyhttp_test.go │ ├── celmatcher.go │ ├── celmatcher_test.go │ ├── encode │ │ ├── brotli │ │ │ └── brotli_precompressed.go │ │ ├── caddyfile.go │ │ ├── encode.go │ │ ├── encode_test.go │ │ ├── gzip │ │ │ ├── gzip.go │ │ │ └── gzip_precompressed.go │ │ └── zstd │ │ │ ├── zstd.go │ │ │ └── zstd_precompressed.go │ ├── errors.go │ ├── fileserver │ │ ├── browse.go │ │ ├── browse.html │ │ ├── browsetplcontext.go │ │ ├── browsetplcontext_test.go │ │ ├── caddyfile.go │ │ ├── command.go │ │ ├── matcher.go │ │ ├── matcher_test.go │ │ ├── staticfiles.go │ │ ├── staticfiles_test.go │ │ └── testdata │ │ │ ├── %D9%85%D9%84%D9%81.txt │ │ │ ├── foo.php.php │ │ │ └── index.php │ │ │ ├── foo.txt │ │ │ ├── foodir │ │ │ ├── bar.txt │ │ │ └── foo.txt │ │ │ ├── index.php │ │ │ ├── large.txt │ │ │ ├── notphp.php.txt │ │ │ ├── remote.php │ │ │ └── ملف.txt │ ├── headers │ │ ├── caddyfile.go │ │ ├── headers.go │ │ └── headers_test.go │ ├── http2listener.go │ ├── httpredirectlistener.go │ ├── intercept │ │ └── intercept.go │ ├── invoke.go │ ├── ip_matchers.go │ ├── ip_range.go │ ├── logging.go │ ├── logging │ │ ├── caddyfile.go │ │ └── logadd.go │ ├── map │ │ ├── caddyfile.go │ │ ├── map.go │ │ └── map_test.go │ ├── marshalers.go │ ├── matchers.go │ ├── matchers_test.go │ ├── metrics.go │ ├── metrics_test.go │ ├── proxyprotocol │ │ ├── listenerwrapper.go │ │ ├── module.go │ │ └── policy.go │ ├── push │ │ ├── caddyfile.go │ │ ├── handler.go │ │ ├── link.go │ │ └── link_test.go │ ├── replacer.go │ ├── replacer_test.go │ ├── requestbody │ │ ├── caddyfile.go │ │ └── requestbody.go │ ├── responsematchers.go │ ├── responsematchers_test.go │ ├── responsewriter.go │ ├── responsewriter_test.go │ ├── reverseproxy │ │ ├── addresses.go │ │ ├── addresses_test.go │ │ ├── admin.go │ │ ├── ascii.go │ │ ├── ascii_test.go │ │ ├── buffering_test.go │ │ ├── caddyfile.go │ │ ├── command.go │ │ ├── copyresponse.go │ │ ├── fastcgi │ │ │ ├── caddyfile.go │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fastcgi.go │ │ │ ├── header.go │ │ │ ├── pool.go │ │ │ ├── reader.go │ │ │ ├── record.go │ │ │ └── writer.go │ │ ├── forwardauth │ │ │ └── caddyfile.go │ │ ├── healthchecks.go │ │ ├── hosts.go │ │ ├── httptransport.go │ │ ├── httptransport_test.go │ │ ├── metrics.go │ │ ├── reverseproxy.go │ │ ├── selectionpolicies.go │ │ ├── selectionpolicies_test.go │ │ ├── streaming.go │ │ ├── streaming_test.go │ │ ├── upstreams.go │ │ └── upstreams_test.go │ ├── rewrite │ │ ├── caddyfile.go │ │ ├── rewrite.go │ │ └── rewrite_test.go │ ├── routes.go │ ├── server.go │ ├── server_test.go │ ├── standard │ │ └── imports.go │ ├── staticerror.go │ ├── staticresp.go │ ├── staticresp_test.go │ ├── subroute.go │ ├── templates │ │ ├── caddyfile.go │ │ ├── frontmatter.go │ │ ├── frontmatter_fuzz.go │ │ ├── templates.go │ │ ├── tplcontext.go │ │ └── tplcontext_test.go │ ├── tracing │ │ ├── module.go │ │ ├── module_test.go │ │ ├── tracer.go │ │ ├── tracer_test.go │ │ ├── tracerprovider.go │ │ └── tracerprovider_test.go │ └── vars.go ├── caddypki │ ├── acmeserver │ │ ├── acmeserver.go │ │ ├── caddyfile.go │ │ ├── challenges.go │ │ ├── policy.go │ │ └── policy_test.go │ ├── adminapi.go │ ├── ca.go │ ├── certificates.go │ ├── command.go │ ├── crypto.go │ ├── maintain.go │ └── pki.go ├── caddytls │ ├── acmeissuer.go │ ├── automation.go │ ├── capools.go │ ├── capools_test.go │ ├── certmanagers.go │ ├── certselection.go │ ├── connpolicy.go │ ├── connpolicy_test.go │ ├── distributedstek │ │ └── distributedstek.go │ ├── ech.go │ ├── fileloader.go │ ├── folderloader.go │ ├── internalissuer.go │ ├── leaffileloader.go │ ├── leaffileloader_test.go │ ├── leaffolderloader.go │ ├── leaffolderloader_test.go │ ├── leafpemloader.go │ ├── leafpemloader_test.go │ ├── leafstorageloader.go │ ├── matchers.go │ ├── matchers_test.go │ ├── ondemand.go │ ├── pemloader.go │ ├── sessiontickets.go │ ├── standardstek │ │ └── stek.go │ ├── storageloader.go │ ├── tls.go │ ├── values.go │ └── zerosslissuer.go ├── filestorage │ └── filestorage.go ├── internal │ └── network │ │ └── networkproxy.go ├── logging │ ├── appendencoder.go │ ├── cores.go │ ├── encoders.go │ ├── filewriter.go │ ├── filewriter_test.go │ ├── filewriter_test_windows.go │ ├── filterencoder.go │ ├── filters.go │ ├── filters_test.go │ ├── netwriter.go │ └── nopencoder.go ├── metrics │ ├── adminmetrics.go │ ├── metrics.go │ └── metrics_test.go └── standard │ └── imports.go ├── modules_test.go ├── notify ├── notify_linux.go ├── notify_other.go └── notify_windows.go ├── replacer.go ├── replacer_fuzz.go ├── replacer_test.go ├── service_windows.go ├── sigtrap.go ├── sigtrap_nonposix.go ├── sigtrap_posix.go ├── storage.go └── usagepool.go /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | 4 | [caddytest/integration/caddyfile_adapt/*.caddyfiletest] 5 | indent_style = tab -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.go text eol=lf -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [mholt] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "monthly" 8 | -------------------------------------------------------------------------------- /.github/workflows/cross-build.yml: -------------------------------------------------------------------------------- 1 | name: Cross-Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - 2.* 8 | pull_request: 9 | branches: 10 | - master 11 | - 2.* 12 | 13 | env: 14 | # https://github.com/actions/setup-go/issues/491 15 | GOTOOLCHAIN: local 16 | 17 | jobs: 18 | build: 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | goos: 23 | - 'aix' 24 | - 'linux' 25 | - 'solaris' 26 | - 'illumos' 27 | - 'dragonfly' 28 | - 'freebsd' 29 | - 'openbsd' 30 | - 'windows' 31 | - 'darwin' 32 | - 'netbsd' 33 | go: 34 | - '1.24' 35 | 36 | include: 37 | # Set the minimum Go patch version for the given Go minor 38 | # Usable via ${{ matrix.GO_SEMVER }} 39 | - go: '1.24' 40 | GO_SEMVER: '~1.24.1' 41 | 42 | runs-on: ubuntu-latest 43 | continue-on-error: true 44 | steps: 45 | - name: Checkout code 46 | uses: actions/checkout@v4 47 | 48 | - name: Install Go 49 | uses: actions/setup-go@v5 50 | with: 51 | go-version: ${{ matrix.GO_SEMVER }} 52 | check-latest: true 53 | 54 | - name: Print Go version and environment 55 | id: vars 56 | run: | 57 | printf "Using go at: $(which go)\n" 58 | printf "Go version: $(go version)\n" 59 | printf "\n\nGo environment:\n\n" 60 | go env 61 | printf "\n\nSystem environment:\n\n" 62 | env 63 | 64 | - name: Run Build 65 | env: 66 | CGO_ENABLED: 0 67 | GOOS: ${{ matrix.goos }} 68 | GOARCH: ${{ matrix.goos == 'aix' && 'ppc64' || 'amd64' }} 69 | shell: bash 70 | continue-on-error: true 71 | working-directory: ./cmd/caddy 72 | run: | 73 | GOOS=$GOOS GOARCH=$GOARCH go build -tags=nobadger,nomysql,nopgx -trimpath -o caddy-"$GOOS"-$GOARCH 2> /dev/null 74 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - 2.* 8 | pull_request: 9 | branches: 10 | - master 11 | - 2.* 12 | 13 | permissions: 14 | contents: read 15 | 16 | env: 17 | # https://github.com/actions/setup-go/issues/491 18 | GOTOOLCHAIN: local 19 | 20 | jobs: 21 | # From https://github.com/golangci/golangci-lint-action 22 | golangci: 23 | permissions: 24 | contents: read # for actions/checkout to fetch code 25 | pull-requests: read # for golangci/golangci-lint-action to fetch pull requests 26 | name: lint 27 | strategy: 28 | matrix: 29 | os: 30 | - linux 31 | - mac 32 | - windows 33 | 34 | include: 35 | - os: linux 36 | OS_LABEL: ubuntu-latest 37 | 38 | - os: mac 39 | OS_LABEL: macos-14 40 | 41 | - os: windows 42 | OS_LABEL: windows-latest 43 | 44 | runs-on: ${{ matrix.OS_LABEL }} 45 | 46 | steps: 47 | - uses: actions/checkout@v4 48 | - uses: actions/setup-go@v5 49 | with: 50 | go-version: '~1.24' 51 | check-latest: true 52 | 53 | - name: golangci-lint 54 | uses: golangci/golangci-lint-action@v6 55 | with: 56 | version: latest 57 | 58 | # Windows times out frequently after about 5m50s if we don't set a longer timeout. 59 | args: --timeout 10m 60 | 61 | # Optional: show only new issues if it's a pull request. The default value is `false`. 62 | # only-new-issues: true 63 | 64 | govulncheck: 65 | runs-on: ubuntu-latest 66 | steps: 67 | - name: govulncheck 68 | uses: golang/govulncheck-action@v1 69 | with: 70 | go-version-input: '~1.24.1' 71 | check-latest: true 72 | -------------------------------------------------------------------------------- /.github/workflows/release_published.yml: -------------------------------------------------------------------------------- 1 | name: Release Published 2 | 3 | # Event payload: https://developer.github.com/webhooks/event-payloads/#release 4 | on: 5 | release: 6 | types: [published] 7 | 8 | jobs: 9 | release: 10 | name: Release Published 11 | strategy: 12 | matrix: 13 | os: 14 | - ubuntu-latest 15 | runs-on: ${{ matrix.os }} 16 | 17 | steps: 18 | 19 | # See https://github.com/peter-evans/repository-dispatch 20 | - name: Trigger event on caddyserver/dist 21 | uses: peter-evans/repository-dispatch@v3 22 | with: 23 | token: ${{ secrets.REPO_DISPATCH_TOKEN }} 24 | repository: caddyserver/dist 25 | event-type: release-tagged 26 | client-payload: '{"tag": "${{ github.event.release.tag_name }}"}' 27 | 28 | - name: Trigger event on caddyserver/caddy-docker 29 | uses: peter-evans/repository-dispatch@v3 30 | with: 31 | token: ${{ secrets.REPO_DISPATCH_TOKEN }} 32 | repository: caddyserver/caddy-docker 33 | event-type: release-tagged 34 | client-payload: '{"tag": "${{ github.event.release.tag_name }}"}' 35 | 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _gitignore/ 2 | *.log 3 | Caddyfile 4 | Caddyfile.* 5 | !caddyfile/ 6 | !caddyfile.go 7 | 8 | # artifacts from pprof tooling 9 | *.prof 10 | *.test 11 | 12 | # build artifacts and helpers 13 | cmd/caddy/caddy 14 | cmd/caddy/caddy.exe 15 | cmd/caddy/tmp/*.exe 16 | cmd/caddy/.env 17 | 18 | # mac specific 19 | .DS_Store 20 | 21 | # go modules 22 | vendor 23 | 24 | # goreleaser artifacts 25 | dist 26 | caddy-build 27 | caddy-dist 28 | 29 | # IDE files 30 | .idea/ 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Caddy Authors for copyright purposes. 2 | # Authors may be either individual people or legal entities. 3 | # 4 | # Not all individual contributors are authors. For the full list of 5 | # contributors, refer to the project's page on GitHub or the repo's 6 | # commit history. 7 | 8 | Matthew Holt 9 | Light Code Labs 10 | Ardan Labs 11 | -------------------------------------------------------------------------------- /caddy_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package caddy 16 | 17 | import ( 18 | "testing" 19 | "time" 20 | ) 21 | 22 | func TestParseDuration(t *testing.T) { 23 | const day = 24 * time.Hour 24 | for i, tc := range []struct { 25 | input string 26 | expect time.Duration 27 | }{ 28 | { 29 | input: "3h", 30 | expect: 3 * time.Hour, 31 | }, 32 | { 33 | input: "1d", 34 | expect: day, 35 | }, 36 | { 37 | input: "1d30m", 38 | expect: day + 30*time.Minute, 39 | }, 40 | { 41 | input: "1m2d", 42 | expect: time.Minute + day*2, 43 | }, 44 | { 45 | input: "1m2d30s", 46 | expect: time.Minute + day*2 + 30*time.Second, 47 | }, 48 | { 49 | input: "1d2d", 50 | expect: 3 * day, 51 | }, 52 | { 53 | input: "1.5d", 54 | expect: time.Duration(1.5 * float64(day)), 55 | }, 56 | { 57 | input: "4m1.25d", 58 | expect: 4*time.Minute + time.Duration(1.25*float64(day)), 59 | }, 60 | { 61 | input: "-1.25d12h", 62 | expect: time.Duration(-1.25*float64(day)) - 12*time.Hour, 63 | }, 64 | } { 65 | actual, err := ParseDuration(tc.input) 66 | if err != nil { 67 | t.Errorf("Test %d ('%s'): Got error: %v", i, tc.input, err) 68 | continue 69 | } 70 | if actual != tc.expect { 71 | t.Errorf("Test %d ('%s'): Expected=%s Actual=%s", i, tc.input, tc.expect, actual) 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /caddyconfig/caddyfile/formatter_fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build gofuzz 16 | 17 | package caddyfile 18 | 19 | import "bytes" 20 | 21 | func FuzzFormat(input []byte) int { 22 | formatted := Format(input) 23 | if bytes.Equal(formatted, Format(formatted)) { 24 | return 1 25 | } 26 | return 0 27 | } 28 | -------------------------------------------------------------------------------- /caddyconfig/caddyfile/lexer_fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build gofuzz 16 | 17 | package caddyfile 18 | 19 | func FuzzTokenize(input []byte) int { 20 | tokens, err := Tokenize(input, "Caddyfile") 21 | if err != nil { 22 | return 0 23 | } 24 | if len(tokens) == 0 { 25 | return -1 26 | } 27 | return 1 28 | } 29 | -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/empty.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caddyserver/caddy/5b2eb664188775973cb8254d4e21544572866a47/caddyconfig/caddyfile/testdata/empty.txt -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/glob/.dotfile.txt: -------------------------------------------------------------------------------- 1 | host1 { 2 | dir1 3 | dir2 arg1 4 | } 5 | -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/glob/import_test1.txt: -------------------------------------------------------------------------------- 1 | dir2 arg1 arg2 2 | dir3 -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/import_args0.txt: -------------------------------------------------------------------------------- 1 | {args[0]} -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/import_args1.txt: -------------------------------------------------------------------------------- 1 | {args[0]} {args[1]} -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/import_glob0.txt: -------------------------------------------------------------------------------- 1 | glob0.host0 { 2 | dir2 arg1 3 | } 4 | 5 | glob0.host1 { 6 | } 7 | -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/import_glob1.txt: -------------------------------------------------------------------------------- 1 | glob1.host0 { 2 | dir1 3 | dir2 arg1 4 | } 5 | -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/import_glob2.txt: -------------------------------------------------------------------------------- 1 | glob2.host0 { 2 | dir2 arg1 3 | } 4 | -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/import_recursive0.txt: -------------------------------------------------------------------------------- 1 | import import_recursive0.txt -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/import_recursive1.txt: -------------------------------------------------------------------------------- 1 | import import_recursive2.txt -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/import_recursive2.txt: -------------------------------------------------------------------------------- 1 | import import_recursive3.txt -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/import_recursive3.txt: -------------------------------------------------------------------------------- 1 | import import_recursive1.txt -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/import_test1.txt: -------------------------------------------------------------------------------- 1 | dir2 arg1 arg2 2 | dir3 -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/import_test2.txt: -------------------------------------------------------------------------------- 1 | host1 { 2 | dir1 3 | dir2 arg1 4 | } -------------------------------------------------------------------------------- /caddyconfig/caddyfile/testdata/only_white_space.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |   6 | 7 | 8 | -------------------------------------------------------------------------------- /caddyconfig/httpcaddyfile/addresses_fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build gofuzz 16 | 17 | package httpcaddyfile 18 | 19 | func FuzzParseAddress(data []byte) int { 20 | addr, err := ParseAddress(string(data)) 21 | if err != nil { 22 | if addr == (Address{}) { 23 | return 1 24 | } 25 | return 0 26 | } 27 | return 1 28 | } 29 | -------------------------------------------------------------------------------- /caddyconfig/httpcaddyfile/options_test.go: -------------------------------------------------------------------------------- 1 | package httpcaddyfile 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" 7 | _ "github.com/caddyserver/caddy/v2/modules/logging" 8 | ) 9 | 10 | func TestGlobalLogOptionSyntax(t *testing.T) { 11 | for i, tc := range []struct { 12 | input string 13 | output string 14 | expectError bool 15 | }{ 16 | // NOTE: Additional test cases of successful Caddyfile parsing 17 | // are present in: caddytest/integration/caddyfile_adapt/ 18 | { 19 | input: `{ 20 | log default 21 | } 22 | `, 23 | output: `{}`, 24 | expectError: false, 25 | }, 26 | { 27 | input: `{ 28 | log example { 29 | output file foo.log 30 | } 31 | log example { 32 | format json 33 | } 34 | } 35 | `, 36 | expectError: true, 37 | }, 38 | { 39 | input: `{ 40 | log example /foo { 41 | output file foo.log 42 | } 43 | } 44 | `, 45 | expectError: true, 46 | }, 47 | } { 48 | 49 | adapter := caddyfile.Adapter{ 50 | ServerType: ServerType{}, 51 | } 52 | 53 | out, _, err := adapter.Adapt([]byte(tc.input), nil) 54 | 55 | if err != nil != tc.expectError { 56 | t.Errorf("Test %d error expectation failed Expected: %v, got %v", i, tc.expectError, err) 57 | continue 58 | } 59 | 60 | if string(out) != tc.output { 61 | t.Errorf("Test %d error output mismatch Expected: %s, got %s", i, tc.output, out) 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /caddyconfig/httpcaddyfile/testdata/import_variadic.txt: -------------------------------------------------------------------------------- 1 | (t2) { 2 | respond 200 { 3 | body {args[:]} 4 | } 5 | } 6 | 7 | :8082 { 8 | import t2 false 9 | } -------------------------------------------------------------------------------- /caddyconfig/httpcaddyfile/testdata/import_variadic_snippet.txt: -------------------------------------------------------------------------------- 1 | (t1) { 2 | respond 200 { 3 | body {args[:]} 4 | } 5 | } 6 | 7 | :8081 { 8 | import t1 false 9 | } -------------------------------------------------------------------------------- /caddyconfig/httpcaddyfile/testdata/import_variadic_with_import.txt: -------------------------------------------------------------------------------- 1 | (t1) { 2 | respond 200 { 3 | body {args[:]} 4 | } 5 | } 6 | 7 | :8081 { 8 | import t1 false 9 | } 10 | 11 | import import_variadic.txt 12 | 13 | :8083 { 14 | import t2 true 15 | } -------------------------------------------------------------------------------- /caddyconfig/httpcaddyfile/tlsapp_test.go: -------------------------------------------------------------------------------- 1 | package httpcaddyfile 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/caddyserver/caddy/v2/modules/caddytls" 7 | ) 8 | 9 | func TestAutomationPolicyIsSubset(t *testing.T) { 10 | for i, test := range []struct { 11 | a, b []string 12 | expect bool 13 | }{ 14 | { 15 | a: []string{"example.com"}, 16 | b: []string{}, 17 | expect: true, 18 | }, 19 | { 20 | a: []string{}, 21 | b: []string{"example.com"}, 22 | expect: false, 23 | }, 24 | { 25 | a: []string{"foo.example.com"}, 26 | b: []string{"*.example.com"}, 27 | expect: true, 28 | }, 29 | { 30 | a: []string{"foo.example.com"}, 31 | b: []string{"foo.example.com"}, 32 | expect: true, 33 | }, 34 | { 35 | a: []string{"foo.example.com"}, 36 | b: []string{"example.com"}, 37 | expect: false, 38 | }, 39 | { 40 | a: []string{"example.com", "foo.example.com"}, 41 | b: []string{"*.com", "*.*.com"}, 42 | expect: true, 43 | }, 44 | { 45 | a: []string{"example.com", "foo.example.com"}, 46 | b: []string{"*.com"}, 47 | expect: false, 48 | }, 49 | } { 50 | apA := &caddytls.AutomationPolicy{SubjectsRaw: test.a} 51 | apB := &caddytls.AutomationPolicy{SubjectsRaw: test.b} 52 | if actual := automationPolicyIsSubset(apA, apB); actual != test.expect { 53 | t.Errorf("Test %d: Expected %t but got %t (A: %v B: %v)", i, test.expect, actual, test.a, test.b) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /caddytest/a.caddy.localhost.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID5zCCAs8CFG4+w/pqR5AZQ+aVB330uRRRKMF0MA0GCSqGSIb3DQEBCwUAMIGv 3 | MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTlkxGzAZBgNVBAoMEkxvY2FsIERldmVs 4 | b3BlbWVudDEbMBkGA1UEBwwSTG9jYWwgRGV2ZWxvcGVtZW50MRowGAYDVQQDDBFh 5 | LmNhZGR5LmxvY2FsaG9zdDEbMBkGA1UECwwSTG9jYWwgRGV2ZWxvcGVtZW50MSAw 6 | HgYJKoZIhvcNAQkBFhFhZG1pbkBjYWRkeS5sb2NhbDAeFw0yMDAzMTMxODUwMTda 7 | Fw0zMDAzMTExODUwMTdaMIGvMQswCQYDVQQGEwJVUzELMAkGA1UECAwCTlkxGzAZ 8 | BgNVBAoMEkxvY2FsIERldmVsb3BlbWVudDEbMBkGA1UEBwwSTG9jYWwgRGV2ZWxv 9 | cGVtZW50MRowGAYDVQQDDBFhLmNhZGR5LmxvY2FsaG9zdDEbMBkGA1UECwwSTG9j 10 | YWwgRGV2ZWxvcGVtZW50MSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBjYWRkeS5sb2Nh 11 | bDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMd9pC9wF7j0459FndPs 12 | Deud/rq41jEZFsVOVtjQgjS1A5ct6NfeMmSlq8i1F7uaTMPZjbOHzY6y6hzLc9+y 13 | /VWNgyUC543HjXnNTnp9Xug6tBBxOxvRMw5mv2nAyzjBGDePPgN84xKhOXG2Wj3u 14 | fOZ+VPVISefRNvjKfN87WLJ0B0HI9wplG5ASVdPQsWDY1cndrZgt2sxQ/3fjIno4 15 | VvrgRWC9Penizgps/a0ZcFZMD/6HJoX/mSZVa1LjopwbMTXvyHCpXkth21E+rBt6 16 | I9DMHerdioVQcX25CqPmAwePxPZSNGEQo/Qu32kzcmscmYxTtYBhDa+yLuHgGggI 17 | j7ECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAP/94KPtkpYtkWADnhtzDmgQ6Q1pH 18 | SubTUZdCwQtm6/LrvpT+uFNsOj4L3Mv3TVUnIQDmKd5VvR42W2MRBiTN2LQptgEn 19 | C7g9BB+UA9kjL3DPk1pJMjzxLHohh0uNLi7eh4mAj8eNvjz9Z4qMWPQoVS0y7/ZK 20 | cCBRKh2GkIqKm34ih6pX7xmMpPEQsFoTVPRHYJfYD1SZ8Iui+EN+7WqLuJWPsPXw 21 | JM1HuZKn7pZmJU2MZZBsrupHGUvNMbBg2mFJcxt4D1VvU+p+a67PSjpFQ6dJG2re 22 | pZoF+N1vMGAFkxe6UqhcC/bXDX+ILVQHJ+RNhzDO6DcWf8dRrC2LaJk3WA== 23 | -----END CERTIFICATE----- 24 | -------------------------------------------------------------------------------- /caddytest/a.caddy.localhost.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAx32kL3AXuPTjn0Wd0+wN653+urjWMRkWxU5W2NCCNLUDly3o 3 | 194yZKWryLUXu5pMw9mNs4fNjrLqHMtz37L9VY2DJQLnjceNec1Oen1e6Dq0EHE7 4 | G9EzDma/acDLOMEYN48+A3zjEqE5cbZaPe585n5U9UhJ59E2+Mp83ztYsnQHQcj3 5 | CmUbkBJV09CxYNjVyd2tmC3azFD/d+MiejhW+uBFYL096eLOCmz9rRlwVkwP/ocm 6 | hf+ZJlVrUuOinBsxNe/IcKleS2HbUT6sG3oj0Mwd6t2KhVBxfbkKo+YDB4/E9lI0 7 | YRCj9C7faTNyaxyZjFO1gGENr7Iu4eAaCAiPsQIDAQABAoIBAQDD/YFIBeWYlifn 8 | e9risQDAIrp3sk7lb9O6Rwv1+Wxi4hBEABvJsYhq74VFK/3EF4UhyWR5JIvkjYyK 9 | e6w887oGyoA05ZSe65XoO7fFidSrbbkoikZbPv3dQT7/ZCWEfdkQBNAVVyY0UGeC 10 | e3hPbjYRsb5AOSQ694X9idqC6uhqcOrBDjITFrctUoP4S6l9A6a+mLSUIwiICcuh 11 | mrNl+j0lzy7DMXRp/Z5Hyo5kuUlrC0dCLa1UHqtrrK7MR55AVEOihSNp1w+OC+vw 12 | f0VjE4JUtO7RQEQUmD1tDfLXwNfMFeWaobB2W0WMvRg0IqoitiqPxsPHRm56OxfM 13 | SRo/Q7QBAoGBAP8DapzBMuaIcJ7cE8Yl07ZGndWWf8buIKIItGF8rkEO3BXhrIke 14 | EmpOi+ELtpbMOG0APhORZyQ58f4ZOVrqZfneNKtDiEZV4mJZaYUESm1pU+2Y6+y5 15 | g4bpQSVKN0ow0xR+MH7qDYtSlsmBU7qAOz775L7BmMA1Bnu72aN/H1JBAoGBAMhD 16 | OzqCSakHOjUbEd22rPwqWmcIyVyo04gaSmcVVT2dHbqR4/t0gX5a9D9U2qwyO6xi 17 | /R+PXyMd32xIeVR2D/7SQ0x6dK68HXICLV8ofHZ5UQcHbxy5og4v/YxSZVTkN374 18 | cEsUeyB0s/UPOHLktFU5hpIlON72/Rp7b+pNIwFxAoGAczpq+Qu/YTWzlcSh1r4O 19 | 7OT5uqI3eH7vFehTAV3iKxl4zxZa7NY+wfRd9kFhrr/2myIp6pOgBFl+hC+HoBIc 20 | JAyIxf5M3GNAWOpH6MfojYmzV7/qktu8l8BcJGplk0t+hVsDtMUze4nFAqZCXBpH 21 | Kw2M7bjyuZ78H/rgu6TcVUECgYEAo1M5ldE2U/VCApeuLX1TfWDpU8i1uK0zv3d5 22 | oLKkT1i5KzTak3SEO9HgC1qf8PoS8tfUio26UICHe99rnHehOfivzEq+qNdgyF+A 23 | M3BoeZMdgzcL5oh640k+Zte4LtDlddcWdhUhCepD7iPYrNNbQ3pkBwL2a9lRuOxc 24 | 7OC2IPECgYBH8f3OrwXjDltIG1dDvuDPNljxLZbFEFbQyVzMePYNftgZknAyGEdh 25 | NW/LuWeTzstnmz/s6RE3jN5ZrrMa4sW77VA9+yU9QW2dkHqFyukQ4sfuNg6kDDNZ 26 | +lqZYMCLw0M5P9fIbmnIYwey7tXkHfmzoCpnYHGQDN6hL0Bh0zGwmg== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /caddytest/caddy.ca.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDSzCCAjOgAwIBAgIUfIRObjWNUA4jxQ/0x8BOCvE2Vw4wDQYJKoZIhvcNAQEL 3 | BQAwFjEUMBIGA1UEAwwLRWFzeS1SU0EgQ0EwHhcNMTkwODI4MTYyNTU5WhcNMjkw 4 | ODI1MTYyNTU5WjAWMRQwEgYDVQQDDAtFYXN5LVJTQSBDQTCCASIwDQYJKoZIhvcN 5 | AQEBBQADggEPADCCAQoCggEBAK5m5elxhQfMp/3aVJ4JnpN9PUSz6LlP6LePAPFU 6 | 7gqohVVFVtDkChJAG3FNkNQNlieVTja/bgH9IcC6oKbROwdY1h0MvNV8AHHigvl0 7 | 3WuJD8g2ReVFXXwsnrPmKXCFzQyMI6TYk3m2gYrXsZOU1GLnfMRC3KAMRgE2F45t 8 | wOs9hqG169YJ6mM2eQjzjCHWI6S2/iUYvYxRkCOlYUbLsMD/AhgAf1plzg6LPqNx 9 | tdlwxZnA0ytgkmhK67HtzJu0+ovUCsMv0RwcMhsEo9T8nyFAGt9XLZ63X5WpBCTU 10 | ApaAUhnG0XnerjmUWb6eUWw4zev54sEfY5F3x002iQaW6cECAwEAAaOBkDCBjTAd 11 | BgNVHQ4EFgQU4CBUbZsS2GaNIkGRz/cBsD5ivjswUQYDVR0jBEowSIAU4CBUbZsS 12 | 2GaNIkGRz/cBsD5ivjuhGqQYMBYxFDASBgNVBAMMC0Vhc3ktUlNBIENBghR8hE5u 13 | NY1QDiPFD/THwE4K8TZXDjAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkq 14 | hkiG9w0BAQsFAAOCAQEAKB3V4HIzoiO/Ch6WMj9bLJ2FGbpkMrcb/Eq01hT5zcfK 15 | D66lVS1MlK+cRL446Z2b2KDP1oFyVs+qmrmtdwrWgD+nfe2sBmmIHo9m9KygMkEO 16 | fG3MghGTEcS+0cTKEcoHYWYyOqQh6jnedXY8Cdm4GM1hAc9MiL3/sqV8YCVSLNnk 17 | oNysmr06/rZ0MCUZPGUtRmfd0heWhrfzAKw2HLgX+RAmpOE2MZqWcjvqKGyaRiaZ 18 | ks4nJkP6521aC2Lgp0HhCz1j8/uQ5ldoDszCnu/iro0NAsNtudTMD+YoLQxLqdle 19 | Ih6CW+illc2VdXwj7mn6J04yns9jfE2jRjW/yTLFuQ== 20 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /caddytest/caddy.localhost.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID5zCCAs8CFFmAAFKV79uhzxc5qXbUw3oBNsYXMA0GCSqGSIb3DQEBCwUAMIGv 3 | MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTlkxGzAZBgNVBAoMEkxvY2FsIERldmVs 4 | b3BlbWVudDEbMBkGA1UEBwwSTG9jYWwgRGV2ZWxvcGVtZW50MRowGAYDVQQDDBEq 5 | LmNhZGR5LmxvY2FsaG9zdDEbMBkGA1UECwwSTG9jYWwgRGV2ZWxvcGVtZW50MSAw 6 | HgYJKoZIhvcNAQkBFhFhZG1pbkBjYWRkeS5sb2NhbDAeFw0yMDAzMDIwODAxMTZa 7 | Fw0zMDAyMjgwODAxMTZaMIGvMQswCQYDVQQGEwJVUzELMAkGA1UECAwCTlkxGzAZ 8 | BgNVBAoMEkxvY2FsIERldmVsb3BlbWVudDEbMBkGA1UEBwwSTG9jYWwgRGV2ZWxv 9 | cGVtZW50MRowGAYDVQQDDBEqLmNhZGR5LmxvY2FsaG9zdDEbMBkGA1UECwwSTG9j 10 | YWwgRGV2ZWxvcGVtZW50MSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBjYWRkeS5sb2Nh 11 | bDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJngfeirQkWaU8ihgIC5 12 | SKpRQX/3koRjljDK/oCbhLs+wg592kIwVv06l7+mn7NSaNBloabjuA1GqyLRsNLL 13 | ptrv0HvXa5qLx28+icsb2Ny3dJnQaj9w9PwjxQ1qZqEJfWRH1D8Vz9AmB+QSV/Gu 14 | 8e8alGFewlYZVfH1kbxoTT6QorF37TeA3bh1fgKFtzsGYKswcaZNdDBBHzLunCKZ 15 | HU6U6L45hm+yLADj3mmDLafUeiVOt6MRLLoSD1eLRVSXGrNo+brJ87zkZntI9+W1 16 | JxOBoXtZCwka7k2DlAtLihsrmBZA2ZC9yVeu/SQy3qb3iCNnTFTCyAnWeTCr6Tcq 17 | 6w8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAOWfXqpAmD4C3wGiMeZAeaaS4hDAR 18 | +JmN+avPDA6F6Bq7DB4NJuIwVUlaDL2s07w5VJJtW52aZVKoBlgHR5yG/XUli6J7 19 | YUJRmdQJvHUSu26cmKvyoOaTrEYbmvtGICWtZc8uTlMf9wQZbJA4KyxTgEQJDXsZ 20 | B2XFe+wVdhAgEpobYDROi+l/p8TL5z3U24LpwVTcJy5sEZVv7Wfs886IyxU8ORt8 21 | VZNcDiH6V53OIGeiufIhia/mPe6jbLntfGZfIFxtCcow4IA/lTy1ned7K5fmvNNb 22 | ZilxOQUk+wVK8genjdrZVAnAxsYLHJIb5yf9O7rr6fWciVMF3a0k5uNK1w== 23 | -----END CERTIFICATE----- 24 | -------------------------------------------------------------------------------- /caddytest/caddy.localhost.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEAmeB96KtCRZpTyKGAgLlIqlFBf/eShGOWMMr+gJuEuz7CDn3a 3 | QjBW/TqXv6afs1Jo0GWhpuO4DUarItGw0sum2u/Qe9drmovHbz6JyxvY3Ld0mdBq 4 | P3D0/CPFDWpmoQl9ZEfUPxXP0CYH5BJX8a7x7xqUYV7CVhlV8fWRvGhNPpCisXft 5 | N4DduHV+AoW3OwZgqzBxpk10MEEfMu6cIpkdTpTovjmGb7IsAOPeaYMtp9R6JU63 6 | oxEsuhIPV4tFVJcas2j5usnzvORme0j35bUnE4Ghe1kLCRruTYOUC0uKGyuYFkDZ 7 | kL3JV679JDLepveII2dMVMLICdZ5MKvpNyrrDwIDAQABAoIBAFcPK01zb6hfm12c 8 | +k5aBiHOnUdgc/YRPg1XHEz5MEycQkDetZjTLrRQ7UBSbnKPgpu9lIsOtbhVLkgh 9 | 6XAqJroiCou2oruqr+hhsqZGmBiwdvj7cNF6ADGTr05az7v22YneFdinZ481pStF 10 | sZocx+bm2+KHMV5zMSwXKyA0xtdJLxs2yklniDBxSZRppgppq1pDPprP5DkgKPfe 11 | 3ekUmbQd5bHmivhW8ItbJLuf82XSsMBZ9ZhKiKIlWlbKAgiSV3SqnUQb5fi7l8hG 12 | yYZxbuCUIGFwKmEpUBBt/nyxrOlMiNtDh9JhrPmijTV3slq70pCLwLL/Ai2aeear 13 | EVA5VhkCgYEAyAmxfPqc2P7BsDAp67/sA7OEPso9qM4WyuWiVdlX2gb9TLNLYbPX 14 | Kk/UmpAIVzpoTAGY5Zp3wkvdD/ou8uUQsE8ioNn4S1a4G9XURH1wVhcEbUiAKI1S 15 | QVBH9B/Pj3eIp5OTKwob0Wj7DNdxoH7ed/Eok0EaTWzOA8pCWADKv/MCgYEAxOzY 16 | YsX7Nl+eyZr2+9unKyeAK/D1DCT/o99UUAHx72/xaBVP/06cfzpvKBNcF9iYc+fq 17 | R1yIUIrDRoSmYKBq+Kb3+nOg1nrqih/NBTokbTiI4Q+/30OQt0Al1e7y9iNKqV8H 18 | jYZItzluGNrWKedZbATwBwbVCY2jnNl6RMDnS3UCgYBxj3cwQUHLuoyQjjcuO80r 19 | qLzZvIxWiXDNDKIk5HcIMlGYOmz/8U2kGp/SgxQJGQJeq8V2C0QTjGfaCyieAcaA 20 | oNxCvptDgd6RBsoze5bLeNOtiqwe2WOp6n5+q5R0mOJ+Z7vzghCayGNFPgWmnH+F 21 | TeW/+wSIkc0+v5L8TK7NWwKBgBrlWlyLO9deUfqpHqihhICBYaEexOlGuF+yZfqT 22 | eW7BdFBJ8OYm33sFCR+JHV/oZlIWT8o1Wizd9vPPtEWoQ1P4wg/D8Si6GwSIeWEI 23 | YudD/HX4x7T/rmlI6qIAg9CYW18sqoRq3c2gm2fro6qPfYgiWIItLbWjUcBfd7Ki 24 | QjTtAoGARKdRv3jMWL84rlEx1nBRgL3pe9Dt+Uxzde2xT3ZeF+5Hp9NfU01qE6M6 25 | 1I6H64smqpetlsXmCEVKwBemP3pJa6avLKgIYiQvHAD/v4rs9mqgy1RTqtYyGNhR 26 | 1A/6dKkbiZ6wzePLLPasXVZxSKEviXf5gJooqumQVSVhCswyCZ0= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/acme_server_custom_challenges.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | pki { 3 | ca custom-ca { 4 | name "Custom CA" 5 | } 6 | } 7 | } 8 | 9 | acme.example.com { 10 | acme_server { 11 | ca custom-ca 12 | challenges dns-01 13 | } 14 | } 15 | ---------- 16 | { 17 | "apps": { 18 | "http": { 19 | "servers": { 20 | "srv0": { 21 | "listen": [ 22 | ":443" 23 | ], 24 | "routes": [ 25 | { 26 | "match": [ 27 | { 28 | "host": [ 29 | "acme.example.com" 30 | ] 31 | } 32 | ], 33 | "handle": [ 34 | { 35 | "handler": "subroute", 36 | "routes": [ 37 | { 38 | "handle": [ 39 | { 40 | "ca": "custom-ca", 41 | "challenges": [ 42 | "dns-01" 43 | ], 44 | "handler": "acme_server" 45 | } 46 | ] 47 | } 48 | ] 49 | } 50 | ], 51 | "terminal": true 52 | } 53 | ] 54 | } 55 | } 56 | }, 57 | "pki": { 58 | "certificate_authorities": { 59 | "custom-ca": { 60 | "name": "Custom CA" 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/acme_server_default_challenges.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | pki { 3 | ca custom-ca { 4 | name "Custom CA" 5 | } 6 | } 7 | } 8 | 9 | acme.example.com { 10 | acme_server { 11 | ca custom-ca 12 | challenges 13 | } 14 | } 15 | ---------- 16 | { 17 | "apps": { 18 | "http": { 19 | "servers": { 20 | "srv0": { 21 | "listen": [ 22 | ":443" 23 | ], 24 | "routes": [ 25 | { 26 | "match": [ 27 | { 28 | "host": [ 29 | "acme.example.com" 30 | ] 31 | } 32 | ], 33 | "handle": [ 34 | { 35 | "handler": "subroute", 36 | "routes": [ 37 | { 38 | "handle": [ 39 | { 40 | "ca": "custom-ca", 41 | "handler": "acme_server" 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | ], 48 | "terminal": true 49 | } 50 | ] 51 | } 52 | } 53 | }, 54 | "pki": { 55 | "certificate_authorities": { 56 | "custom-ca": { 57 | "name": "Custom CA" 58 | } 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/acme_server_multi_custom_challenges.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | pki { 3 | ca custom-ca { 4 | name "Custom CA" 5 | } 6 | } 7 | } 8 | 9 | acme.example.com { 10 | acme_server { 11 | ca custom-ca 12 | challenges dns-01 http-01 13 | } 14 | } 15 | ---------- 16 | { 17 | "apps": { 18 | "http": { 19 | "servers": { 20 | "srv0": { 21 | "listen": [ 22 | ":443" 23 | ], 24 | "routes": [ 25 | { 26 | "match": [ 27 | { 28 | "host": [ 29 | "acme.example.com" 30 | ] 31 | } 32 | ], 33 | "handle": [ 34 | { 35 | "handler": "subroute", 36 | "routes": [ 37 | { 38 | "handle": [ 39 | { 40 | "ca": "custom-ca", 41 | "challenges": [ 42 | "dns-01", 43 | "http-01" 44 | ], 45 | "handler": "acme_server" 46 | } 47 | ] 48 | } 49 | ] 50 | } 51 | ], 52 | "terminal": true 53 | } 54 | ] 55 | } 56 | } 57 | }, 58 | "pki": { 59 | "certificate_authorities": { 60 | "custom-ca": { 61 | "name": "Custom CA" 62 | } 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/acme_server_policy-allow.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | pki { 3 | ca custom-ca { 4 | name "Custom CA" 5 | } 6 | } 7 | } 8 | 9 | acme.example.com { 10 | acme_server { 11 | ca custom-ca 12 | allow { 13 | domains host-1.internal.example.com host-2.internal.example.com 14 | } 15 | } 16 | } 17 | ---------- 18 | { 19 | "apps": { 20 | "http": { 21 | "servers": { 22 | "srv0": { 23 | "listen": [ 24 | ":443" 25 | ], 26 | "routes": [ 27 | { 28 | "match": [ 29 | { 30 | "host": [ 31 | "acme.example.com" 32 | ] 33 | } 34 | ], 35 | "handle": [ 36 | { 37 | "handler": "subroute", 38 | "routes": [ 39 | { 40 | "handle": [ 41 | { 42 | "ca": "custom-ca", 43 | "handler": "acme_server", 44 | "policy": { 45 | "allow": { 46 | "domains": [ 47 | "host-1.internal.example.com", 48 | "host-2.internal.example.com" 49 | ] 50 | } 51 | } 52 | } 53 | ] 54 | } 55 | ] 56 | } 57 | ], 58 | "terminal": true 59 | } 60 | ] 61 | } 62 | } 63 | }, 64 | "pki": { 65 | "certificate_authorities": { 66 | "custom-ca": { 67 | "name": "Custom CA" 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/acme_server_policy-both.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | pki { 3 | ca custom-ca { 4 | name "Custom CA" 5 | } 6 | } 7 | } 8 | 9 | acme.example.com { 10 | acme_server { 11 | ca custom-ca 12 | allow { 13 | domains host-1.internal.example.com host-2.internal.example.com 14 | } 15 | deny { 16 | domains dc.internal.example.com 17 | } 18 | } 19 | } 20 | ---------- 21 | { 22 | "apps": { 23 | "http": { 24 | "servers": { 25 | "srv0": { 26 | "listen": [ 27 | ":443" 28 | ], 29 | "routes": [ 30 | { 31 | "match": [ 32 | { 33 | "host": [ 34 | "acme.example.com" 35 | ] 36 | } 37 | ], 38 | "handle": [ 39 | { 40 | "handler": "subroute", 41 | "routes": [ 42 | { 43 | "handle": [ 44 | { 45 | "ca": "custom-ca", 46 | "handler": "acme_server", 47 | "policy": { 48 | "allow": { 49 | "domains": [ 50 | "host-1.internal.example.com", 51 | "host-2.internal.example.com" 52 | ] 53 | }, 54 | "deny": { 55 | "domains": [ 56 | "dc.internal.example.com" 57 | ] 58 | } 59 | } 60 | } 61 | ] 62 | } 63 | ] 64 | } 65 | ], 66 | "terminal": true 67 | } 68 | ] 69 | } 70 | } 71 | }, 72 | "pki": { 73 | "certificate_authorities": { 74 | "custom-ca": { 75 | "name": "Custom CA" 76 | } 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/acme_server_policy-deny.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | pki { 3 | ca custom-ca { 4 | name "Custom CA" 5 | } 6 | } 7 | } 8 | 9 | acme.example.com { 10 | acme_server { 11 | ca custom-ca 12 | deny { 13 | domains dc.internal.example.com 14 | } 15 | } 16 | } 17 | ---------- 18 | { 19 | "apps": { 20 | "http": { 21 | "servers": { 22 | "srv0": { 23 | "listen": [ 24 | ":443" 25 | ], 26 | "routes": [ 27 | { 28 | "match": [ 29 | { 30 | "host": [ 31 | "acme.example.com" 32 | ] 33 | } 34 | ], 35 | "handle": [ 36 | { 37 | "handler": "subroute", 38 | "routes": [ 39 | { 40 | "handle": [ 41 | { 42 | "ca": "custom-ca", 43 | "handler": "acme_server", 44 | "policy": { 45 | "deny": { 46 | "domains": [ 47 | "dc.internal.example.com" 48 | ] 49 | } 50 | } 51 | } 52 | ] 53 | } 54 | ] 55 | } 56 | ], 57 | "terminal": true 58 | } 59 | ] 60 | } 61 | } 62 | }, 63 | "pki": { 64 | "certificate_authorities": { 65 | "custom-ca": { 66 | "name": "Custom CA" 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/acme_server_sign_with_root.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | pki { 3 | ca internal { 4 | name "Internal" 5 | root_cn "Internal Root Cert" 6 | intermediate_cn "Internal Intermediate Cert" 7 | } 8 | } 9 | } 10 | acme.example.com { 11 | acme_server { 12 | ca internal 13 | sign_with_root 14 | } 15 | } 16 | 17 | ---------- 18 | { 19 | "apps": { 20 | "http": { 21 | "servers": { 22 | "srv0": { 23 | "listen": [ 24 | ":443" 25 | ], 26 | "routes": [ 27 | { 28 | "match": [ 29 | { 30 | "host": [ 31 | "acme.example.com" 32 | ] 33 | } 34 | ], 35 | "handle": [ 36 | { 37 | "handler": "subroute", 38 | "routes": [ 39 | { 40 | "handle": [ 41 | { 42 | "ca": "internal", 43 | "handler": "acme_server", 44 | "sign_with_root": true 45 | } 46 | ] 47 | } 48 | ] 49 | } 50 | ], 51 | "terminal": true 52 | } 53 | ] 54 | } 55 | } 56 | }, 57 | "pki": { 58 | "certificate_authorities": { 59 | "internal": { 60 | "name": "Internal", 61 | "root_common_name": "Internal Root Cert", 62 | "intermediate_common_name": "Internal Intermediate Cert" 63 | } 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/auto_https_disable_redirects.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | auto_https disable_redirects 3 | } 4 | 5 | localhost 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":443" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "host": [ 20 | "localhost" 21 | ] 22 | } 23 | ], 24 | "terminal": true 25 | } 26 | ], 27 | "automatic_https": { 28 | "disable_redirects": true 29 | } 30 | } 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/auto_https_ignore_loaded_certs.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | auto_https ignore_loaded_certs 3 | } 4 | 5 | localhost 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":443" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "host": [ 20 | "localhost" 21 | ] 22 | } 23 | ], 24 | "terminal": true 25 | } 26 | ], 27 | "automatic_https": { 28 | "ignore_loaded_certificates": true 29 | } 30 | } 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/auto_https_off.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | auto_https off 3 | } 4 | 5 | localhost 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":443" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "host": [ 20 | "localhost" 21 | ] 22 | } 23 | ], 24 | "terminal": true 25 | } 26 | ], 27 | "tls_connection_policies": [ 28 | {} 29 | ], 30 | "automatic_https": { 31 | "disable": true 32 | } 33 | } 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/bind_ipv6.caddyfiletest: -------------------------------------------------------------------------------- 1 | example.com { 2 | bind tcp6/[::] 3 | } 4 | ---------- 5 | { 6 | "apps": { 7 | "http": { 8 | "servers": { 9 | "srv0": { 10 | "listen": [ 11 | "tcp6/[::]:443" 12 | ], 13 | "routes": [ 14 | { 15 | "match": [ 16 | { 17 | "host": [ 18 | "example.com" 19 | ] 20 | } 21 | ], 22 | "terminal": true 23 | } 24 | ] 25 | } 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/enable_tls_for_catch_all_site.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8443 { 2 | tls internal { 3 | on_demand 4 | } 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":8443" 14 | ], 15 | "tls_connection_policies": [ 16 | {} 17 | ] 18 | } 19 | } 20 | }, 21 | "tls": { 22 | "automation": { 23 | "policies": [ 24 | { 25 | "issuers": [ 26 | { 27 | "module": "internal" 28 | } 29 | ], 30 | "on_demand": true 31 | } 32 | ] 33 | } 34 | } 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/file_server_disable_canonical_uris.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | file_server { 4 | disable_canonical_uris 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":80" 14 | ], 15 | "routes": [ 16 | { 17 | "handle": [ 18 | { 19 | "canonical_uris": false, 20 | "handler": "file_server", 21 | "hide": [ 22 | "./Caddyfile" 23 | ] 24 | } 25 | ] 26 | } 27 | ] 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/file_server_etag_file_extensions.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8080 { 2 | root * ./ 3 | file_server { 4 | etag_file_extensions .b3sum .sha256 5 | } 6 | } 7 | ---------- 8 | { 9 | "apps": { 10 | "http": { 11 | "servers": { 12 | "srv0": { 13 | "listen": [ 14 | ":8080" 15 | ], 16 | "routes": [ 17 | { 18 | "handle": [ 19 | { 20 | "handler": "vars", 21 | "root": "./" 22 | }, 23 | { 24 | "etag_file_extensions": [ 25 | ".b3sum", 26 | ".sha256" 27 | ], 28 | "handler": "file_server", 29 | "hide": [ 30 | "./Caddyfile" 31 | ] 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/file_server_file_limit.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | file_server { 4 | browse { 5 | file_limit 4000 6 | } 7 | } 8 | ---------- 9 | { 10 | "apps": { 11 | "http": { 12 | "servers": { 13 | "srv0": { 14 | "listen": [ 15 | ":80" 16 | ], 17 | "routes": [ 18 | { 19 | "handle": [ 20 | { 21 | "browse": { 22 | "file_limit": 4000 23 | }, 24 | "handler": "file_server", 25 | "hide": [ 26 | "./Caddyfile" 27 | ] 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/file_server_pass_thru.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | file_server { 4 | pass_thru 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":80" 14 | ], 15 | "routes": [ 16 | { 17 | "handle": [ 18 | { 19 | "handler": "file_server", 20 | "hide": [ 21 | "./Caddyfile" 22 | ], 23 | "pass_thru": true 24 | } 25 | ] 26 | } 27 | ] 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/file_server_precompressed.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | file_server { 4 | precompressed zstd br gzip 5 | } 6 | 7 | file_server { 8 | precompressed 9 | } 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":80" 18 | ], 19 | "routes": [ 20 | { 21 | "handle": [ 22 | { 23 | "handler": "file_server", 24 | "hide": [ 25 | "./Caddyfile" 26 | ], 27 | "precompressed": { 28 | "br": {}, 29 | "gzip": {}, 30 | "zstd": {} 31 | }, 32 | "precompressed_order": [ 33 | "zstd", 34 | "br", 35 | "gzip" 36 | ] 37 | }, 38 | { 39 | "handler": "file_server", 40 | "hide": [ 41 | "./Caddyfile" 42 | ], 43 | "precompressed": { 44 | "br": {}, 45 | "gzip": {}, 46 | "zstd": {} 47 | }, 48 | "precompressed_order": [ 49 | "br", 50 | "zstd", 51 | "gzip" 52 | ] 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/file_server_sort.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | file_server { 4 | browse { 5 | sort size desc 6 | } 7 | } 8 | ---------- 9 | { 10 | "apps": { 11 | "http": { 12 | "servers": { 13 | "srv0": { 14 | "listen": [ 15 | ":80" 16 | ], 17 | "routes": [ 18 | { 19 | "handle": [ 20 | { 21 | "browse": { 22 | "sort": [ 23 | "size", 24 | "desc" 25 | ] 26 | }, 27 | "handler": "file_server", 28 | "hide": [ 29 | "./Caddyfile" 30 | ] 31 | } 32 | ] 33 | } 34 | ] 35 | } 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | debug 3 | http_port 8080 4 | https_port 8443 5 | grace_period 5s 6 | shutdown_delay 10s 7 | default_sni localhost 8 | order root first 9 | storage file_system { 10 | root /data 11 | } 12 | storage_check off 13 | storage_clean_interval off 14 | acme_ca https://example.com 15 | acme_ca_root /path/to/ca.crt 16 | ocsp_stapling off 17 | 18 | email test@example.com 19 | admin off 20 | on_demand_tls { 21 | ask https://example.com 22 | } 23 | local_certs 24 | key_type ed25519 25 | } 26 | 27 | :80 28 | ---------- 29 | { 30 | "admin": { 31 | "disabled": true 32 | }, 33 | "logging": { 34 | "logs": { 35 | "default": { 36 | "level": "DEBUG" 37 | } 38 | } 39 | }, 40 | "storage": { 41 | "module": "file_system", 42 | "root": "/data" 43 | }, 44 | "apps": { 45 | "http": { 46 | "http_port": 8080, 47 | "https_port": 8443, 48 | "grace_period": 5000000000, 49 | "shutdown_delay": 10000000000, 50 | "servers": { 51 | "srv0": { 52 | "listen": [ 53 | ":80" 54 | ] 55 | } 56 | } 57 | }, 58 | "tls": { 59 | "automation": { 60 | "policies": [ 61 | { 62 | "issuers": [ 63 | { 64 | "module": "internal" 65 | } 66 | ], 67 | "key_type": "ed25519", 68 | "disable_ocsp_stapling": true 69 | } 70 | ], 71 | "on_demand": { 72 | "permission": { 73 | "endpoint": "https://example.com", 74 | "module": "http" 75 | } 76 | } 77 | }, 78 | "disable_ocsp_stapling": true, 79 | "disable_storage_check": true, 80 | "disable_storage_clean": true 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options_admin.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | debug 3 | http_port 8080 4 | https_port 8443 5 | default_sni localhost 6 | order root first 7 | storage file_system { 8 | root /data 9 | } 10 | acme_ca https://example.com 11 | acme_ca_root /path/to/ca.crt 12 | 13 | email test@example.com 14 | admin { 15 | origins localhost:2019 [::1]:2019 127.0.0.1:2019 192.168.10.128 16 | } 17 | on_demand_tls { 18 | ask https://example.com 19 | } 20 | local_certs 21 | key_type ed25519 22 | } 23 | 24 | :80 25 | ---------- 26 | { 27 | "admin": { 28 | "listen": "localhost:2019", 29 | "origins": [ 30 | "localhost:2019", 31 | "[::1]:2019", 32 | "127.0.0.1:2019", 33 | "192.168.10.128" 34 | ] 35 | }, 36 | "logging": { 37 | "logs": { 38 | "default": { 39 | "level": "DEBUG" 40 | } 41 | } 42 | }, 43 | "storage": { 44 | "module": "file_system", 45 | "root": "/data" 46 | }, 47 | "apps": { 48 | "http": { 49 | "http_port": 8080, 50 | "https_port": 8443, 51 | "servers": { 52 | "srv0": { 53 | "listen": [ 54 | ":80" 55 | ] 56 | } 57 | } 58 | }, 59 | "tls": { 60 | "automation": { 61 | "policies": [ 62 | { 63 | "issuers": [ 64 | { 65 | "module": "internal" 66 | } 67 | ], 68 | "key_type": "ed25519" 69 | } 70 | ], 71 | "on_demand": { 72 | "permission": { 73 | "endpoint": "https://example.com", 74 | "module": "http" 75 | } 76 | } 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options_admin_with_persist_config_off.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | http_port 8080 3 | persist_config off 4 | admin { 5 | origins localhost:2019 [::1]:2019 127.0.0.1:2019 192.168.10.128 6 | } 7 | } 8 | 9 | :80 10 | ---------- 11 | { 12 | "admin": { 13 | "listen": "localhost:2019", 14 | "origins": [ 15 | "localhost:2019", 16 | "[::1]:2019", 17 | "127.0.0.1:2019", 18 | "192.168.10.128" 19 | ], 20 | "config": { 21 | "persist": false 22 | } 23 | }, 24 | "apps": { 25 | "http": { 26 | "http_port": 8080, 27 | "servers": { 28 | "srv0": { 29 | "listen": [ 30 | ":80" 31 | ] 32 | } 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options_debug_with_access_log.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | debug 3 | } 4 | 5 | :8881 { 6 | log { 7 | format console 8 | } 9 | } 10 | ---------- 11 | { 12 | "logging": { 13 | "logs": { 14 | "default": { 15 | "level": "DEBUG", 16 | "exclude": [ 17 | "http.log.access.log0" 18 | ] 19 | }, 20 | "log0": { 21 | "encoder": { 22 | "format": "console" 23 | }, 24 | "level": "DEBUG", 25 | "include": [ 26 | "http.log.access.log0" 27 | ] 28 | } 29 | } 30 | }, 31 | "apps": { 32 | "http": { 33 | "servers": { 34 | "srv0": { 35 | "listen": [ 36 | ":8881" 37 | ], 38 | "logs": { 39 | "default_logger_name": "log0" 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options_default_bind.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | default_bind tcp4/0.0.0.0 tcp6/[::] 3 | } 4 | 5 | example.com { 6 | } 7 | 8 | example.org:12345 { 9 | } 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | "tcp4/0.0.0.0:12345", 18 | "tcp6/[::]:12345" 19 | ], 20 | "routes": [ 21 | { 22 | "match": [ 23 | { 24 | "host": [ 25 | "example.org" 26 | ] 27 | } 28 | ], 29 | "terminal": true 30 | } 31 | ] 32 | }, 33 | "srv1": { 34 | "listen": [ 35 | "tcp4/0.0.0.0:443", 36 | "tcp6/[::]:443" 37 | ], 38 | "routes": [ 39 | { 40 | "match": [ 41 | { 42 | "host": [ 43 | "example.com" 44 | ] 45 | } 46 | ], 47 | "terminal": true 48 | } 49 | ] 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options_log_and_site.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | log { 3 | output file caddy.log 4 | include some-log-source 5 | exclude admin.api admin2.api 6 | } 7 | log custom-logger { 8 | output file caddy.log 9 | level WARN 10 | include custom-log-source 11 | } 12 | } 13 | 14 | :8884 { 15 | log { 16 | format json 17 | output file access.log 18 | } 19 | } 20 | ---------- 21 | { 22 | "logging": { 23 | "logs": { 24 | "custom-logger": { 25 | "writer": { 26 | "filename": "caddy.log", 27 | "output": "file" 28 | }, 29 | "level": "WARN", 30 | "include": [ 31 | "custom-log-source" 32 | ] 33 | }, 34 | "default": { 35 | "writer": { 36 | "filename": "caddy.log", 37 | "output": "file" 38 | }, 39 | "include": [ 40 | "some-log-source" 41 | ], 42 | "exclude": [ 43 | "admin.api", 44 | "admin2.api", 45 | "custom-log-source", 46 | "http.log.access.log0" 47 | ] 48 | }, 49 | "log0": { 50 | "writer": { 51 | "filename": "access.log", 52 | "output": "file" 53 | }, 54 | "encoder": { 55 | "format": "json" 56 | }, 57 | "include": [ 58 | "http.log.access.log0" 59 | ] 60 | } 61 | } 62 | }, 63 | "apps": { 64 | "http": { 65 | "servers": { 66 | "srv0": { 67 | "listen": [ 68 | ":8884" 69 | ], 70 | "logs": { 71 | "default_logger_name": "log0" 72 | } 73 | } 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options_log_basic.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | log { 3 | output file foo.log 4 | } 5 | } 6 | ---------- 7 | { 8 | "logging": { 9 | "logs": { 10 | "default": { 11 | "writer": { 12 | "filename": "foo.log", 13 | "output": "file" 14 | } 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options_log_custom.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | log custom-logger { 3 | format filter { 4 | wrap console 5 | fields { 6 | request>remote_ip ip_mask { 7 | ipv4 24 8 | ipv6 32 9 | } 10 | } 11 | } 12 | } 13 | } 14 | ---------- 15 | { 16 | "logging": { 17 | "logs": { 18 | "custom-logger": { 19 | "encoder": { 20 | "fields": { 21 | "request\u003eremote_ip": { 22 | "filter": "ip_mask", 23 | "ipv4_cidr": 24, 24 | "ipv6_cidr": 32 25 | } 26 | }, 27 | "format": "filter", 28 | "wrap": { 29 | "format": "console" 30 | } 31 | } 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options_log_multi.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | log first { 3 | output file foo.log 4 | } 5 | log second { 6 | format json 7 | } 8 | } 9 | ---------- 10 | { 11 | "logging": { 12 | "logs": { 13 | "first": { 14 | "writer": { 15 | "filename": "foo.log", 16 | "output": "file" 17 | } 18 | }, 19 | "second": { 20 | "encoder": { 21 | "format": "json" 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options_log_sampling.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | log { 3 | sampling { 4 | interval 300 5 | first 50 6 | thereafter 40 7 | } 8 | } 9 | } 10 | ---------- 11 | { 12 | "logging": { 13 | "logs": { 14 | "default": { 15 | "sampling": { 16 | "interval": 300, 17 | "first": 50, 18 | "thereafter": 40 19 | } 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options_persist_config.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | persist_config off 3 | } 4 | 5 | :8881 { 6 | } 7 | ---------- 8 | { 9 | "admin": { 10 | "config": { 11 | "persist": false 12 | } 13 | }, 14 | "apps": { 15 | "http": { 16 | "servers": { 17 | "srv0": { 18 | "listen": [ 19 | ":8881" 20 | ] 21 | } 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_options_preferred_chains.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | preferred_chains smallest 3 | } 4 | 5 | example.com 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":443" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "host": [ 20 | "example.com" 21 | ] 22 | } 23 | ], 24 | "terminal": true 25 | } 26 | ] 27 | } 28 | } 29 | }, 30 | "tls": { 31 | "automation": { 32 | "policies": [ 33 | { 34 | "subjects": [ 35 | "example.com" 36 | ], 37 | "issuers": [ 38 | { 39 | "module": "acme", 40 | "preferred_chains": { 41 | "smallest": true 42 | } 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_server_options_multi.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | servers { 3 | timeouts { 4 | idle 90s 5 | } 6 | strict_sni_host insecure_off 7 | } 8 | servers :80 { 9 | timeouts { 10 | idle 60s 11 | } 12 | } 13 | servers :443 { 14 | timeouts { 15 | idle 30s 16 | } 17 | strict_sni_host 18 | } 19 | } 20 | 21 | foo.com { 22 | } 23 | 24 | http://bar.com { 25 | } 26 | 27 | :8080 { 28 | } 29 | 30 | ---------- 31 | { 32 | "apps": { 33 | "http": { 34 | "servers": { 35 | "srv0": { 36 | "listen": [ 37 | ":443" 38 | ], 39 | "idle_timeout": 30000000000, 40 | "routes": [ 41 | { 42 | "match": [ 43 | { 44 | "host": [ 45 | "foo.com" 46 | ] 47 | } 48 | ], 49 | "terminal": true 50 | } 51 | ], 52 | "strict_sni_host": true 53 | }, 54 | "srv1": { 55 | "listen": [ 56 | ":80" 57 | ], 58 | "idle_timeout": 60000000000, 59 | "routes": [ 60 | { 61 | "match": [ 62 | { 63 | "host": [ 64 | "bar.com" 65 | ] 66 | } 67 | ], 68 | "terminal": true 69 | } 70 | ] 71 | }, 72 | "srv2": { 73 | "listen": [ 74 | ":8080" 75 | ], 76 | "idle_timeout": 90000000000, 77 | "strict_sni_host": false 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/global_server_options_single.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | servers { 3 | listener_wrappers { 4 | http_redirect 5 | tls 6 | } 7 | timeouts { 8 | read_body 30s 9 | read_header 30s 10 | write 30s 11 | idle 30s 12 | } 13 | max_header_size 100MB 14 | enable_full_duplex 15 | log_credentials 16 | protocols h1 h2 h2c h3 17 | strict_sni_host 18 | trusted_proxies static private_ranges 19 | client_ip_headers Custom-Real-Client-IP X-Forwarded-For 20 | client_ip_headers A-Third-One 21 | } 22 | } 23 | 24 | foo.com { 25 | } 26 | 27 | ---------- 28 | { 29 | "apps": { 30 | "http": { 31 | "servers": { 32 | "srv0": { 33 | "listen": [ 34 | ":443" 35 | ], 36 | "listener_wrappers": [ 37 | { 38 | "wrapper": "http_redirect" 39 | }, 40 | { 41 | "wrapper": "tls" 42 | } 43 | ], 44 | "read_timeout": 30000000000, 45 | "read_header_timeout": 30000000000, 46 | "write_timeout": 30000000000, 47 | "idle_timeout": 30000000000, 48 | "max_header_bytes": 100000000, 49 | "enable_full_duplex": true, 50 | "routes": [ 51 | { 52 | "match": [ 53 | { 54 | "host": [ 55 | "foo.com" 56 | ] 57 | } 58 | ], 59 | "terminal": true 60 | } 61 | ], 62 | "strict_sni_host": true, 63 | "trusted_proxies": { 64 | "ranges": [ 65 | "192.168.0.0/16", 66 | "172.16.0.0/12", 67 | "10.0.0.0/8", 68 | "127.0.0.1/8", 69 | "fd00::/8", 70 | "::1" 71 | ], 72 | "source": "static" 73 | }, 74 | "client_ip_headers": [ 75 | "Custom-Real-Client-IP", 76 | "X-Forwarded-For", 77 | "A-Third-One" 78 | ], 79 | "logs": { 80 | "should_log_credentials": true 81 | }, 82 | "protocols": [ 83 | "h1", 84 | "h2", 85 | "h2c", 86 | "h3" 87 | ] 88 | } 89 | } 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/handle_nested_in_route.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8881 { 2 | route { 3 | handle /foo/* { 4 | respond "Foo" 5 | } 6 | handle { 7 | respond "Bar" 8 | } 9 | } 10 | } 11 | ---------- 12 | { 13 | "apps": { 14 | "http": { 15 | "servers": { 16 | "srv0": { 17 | "listen": [ 18 | ":8881" 19 | ], 20 | "routes": [ 21 | { 22 | "handle": [ 23 | { 24 | "handler": "subroute", 25 | "routes": [ 26 | { 27 | "group": "group2", 28 | "handle": [ 29 | { 30 | "handler": "subroute", 31 | "routes": [ 32 | { 33 | "handle": [ 34 | { 35 | "body": "Foo", 36 | "handler": "static_response" 37 | } 38 | ] 39 | } 40 | ] 41 | } 42 | ], 43 | "match": [ 44 | { 45 | "path": [ 46 | "/foo/*" 47 | ] 48 | } 49 | ] 50 | }, 51 | { 52 | "group": "group2", 53 | "handle": [ 54 | { 55 | "handler": "subroute", 56 | "routes": [ 57 | { 58 | "handle": [ 59 | { 60 | "body": "Bar", 61 | "handler": "static_response" 62 | } 63 | ] 64 | } 65 | ] 66 | } 67 | ] 68 | } 69 | ] 70 | } 71 | ] 72 | } 73 | ] 74 | } 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/handle_path.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | handle_path /api/v1/* { 3 | respond "API v1" 4 | } 5 | ---------- 6 | { 7 | "apps": { 8 | "http": { 9 | "servers": { 10 | "srv0": { 11 | "listen": [ 12 | ":80" 13 | ], 14 | "routes": [ 15 | { 16 | "match": [ 17 | { 18 | "path": [ 19 | "/api/v1/*" 20 | ] 21 | } 22 | ], 23 | "handle": [ 24 | { 25 | "handler": "subroute", 26 | "routes": [ 27 | { 28 | "handle": [ 29 | { 30 | "handler": "rewrite", 31 | "strip_path_prefix": "/api/v1" 32 | } 33 | ] 34 | }, 35 | { 36 | "handle": [ 37 | { 38 | "body": "API v1", 39 | "handler": "static_response" 40 | } 41 | ] 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | ] 48 | } 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/heredoc.caddyfiletest: -------------------------------------------------------------------------------- 1 | example.com { 2 | respond < 4 | Foo 5 | Foo 6 | 7 | EOF 200 8 | } 9 | 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":443" 18 | ], 19 | "routes": [ 20 | { 21 | "match": [ 22 | { 23 | "host": [ 24 | "example.com" 25 | ] 26 | } 27 | ], 28 | "handle": [ 29 | { 30 | "handler": "subroute", 31 | "routes": [ 32 | { 33 | "handle": [ 34 | { 35 | "body": "\u003chtml\u003e\n \u003chead\u003e\u003ctitle\u003eFoo\u003c/title\u003e\n \u003cbody\u003eFoo\u003c/body\u003e\n\u003c/html\u003e", 36 | "handler": "static_response", 37 | "status_code": 200 38 | } 39 | ] 40 | } 41 | ] 42 | } 43 | ], 44 | "terminal": true 45 | } 46 | ] 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/http_only_hostnames.caddyfiletest: -------------------------------------------------------------------------------- 1 | # https://github.com/caddyserver/caddy/issues/3977 2 | http://* { 3 | respond "Hello, world!" 4 | } 5 | ---------- 6 | { 7 | "apps": { 8 | "http": { 9 | "servers": { 10 | "srv0": { 11 | "listen": [ 12 | ":80" 13 | ], 14 | "routes": [ 15 | { 16 | "match": [ 17 | { 18 | "host": [ 19 | "*" 20 | ] 21 | } 22 | ], 23 | "handle": [ 24 | { 25 | "handler": "subroute", 26 | "routes": [ 27 | { 28 | "handle": [ 29 | { 30 | "body": "Hello, world!", 31 | "handler": "static_response" 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | ], 38 | "terminal": true 39 | } 40 | ] 41 | } 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/http_only_on_any_address.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 { 2 | respond /version 200 { 3 | body "hello from localhost" 4 | } 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":80" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "path": [ 20 | "/version" 21 | ] 22 | } 23 | ], 24 | "handle": [ 25 | { 26 | "body": "hello from localhost", 27 | "handler": "static_response", 28 | "status_code": 200 29 | } 30 | ] 31 | } 32 | ] 33 | } 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/http_only_on_domain.caddyfiletest: -------------------------------------------------------------------------------- 1 | http://a.caddy.localhost { 2 | respond /version 200 { 3 | body "hello from localhost" 4 | } 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":80" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "host": [ 20 | "a.caddy.localhost" 21 | ] 22 | } 23 | ], 24 | "handle": [ 25 | { 26 | "handler": "subroute", 27 | "routes": [ 28 | { 29 | "handle": [ 30 | { 31 | "body": "hello from localhost", 32 | "handler": "static_response", 33 | "status_code": 200 34 | } 35 | ], 36 | "match": [ 37 | { 38 | "path": [ 39 | "/version" 40 | ] 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | ], 47 | "terminal": true 48 | } 49 | ] 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/http_only_on_hostless_block.caddyfiletest: -------------------------------------------------------------------------------- 1 | # Issue #4113 2 | :80, http://example.com { 3 | respond "foo" 4 | } 5 | ---------- 6 | { 7 | "apps": { 8 | "http": { 9 | "servers": { 10 | "srv0": { 11 | "listen": [ 12 | ":80" 13 | ], 14 | "routes": [ 15 | { 16 | "handle": [ 17 | { 18 | "body": "foo", 19 | "handler": "static_response" 20 | } 21 | ] 22 | } 23 | ] 24 | } 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/http_only_on_localhost.caddyfiletest: -------------------------------------------------------------------------------- 1 | localhost:80 { 2 | respond /version 200 { 3 | body "hello from localhost" 4 | } 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":80" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "host": [ 20 | "localhost" 21 | ] 22 | } 23 | ], 24 | "handle": [ 25 | { 26 | "handler": "subroute", 27 | "routes": [ 28 | { 29 | "handle": [ 30 | { 31 | "body": "hello from localhost", 32 | "handler": "static_response", 33 | "status_code": 200 34 | } 35 | ], 36 | "match": [ 37 | { 38 | "path": [ 39 | "/version" 40 | ] 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | ], 47 | "terminal": true 48 | } 49 | ] 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/http_only_on_non_standard_port.caddyfiletest: -------------------------------------------------------------------------------- 1 | http://a.caddy.localhost:81 { 2 | respond /version 200 { 3 | body "hello from localhost" 4 | } 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":81" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "host": [ 20 | "a.caddy.localhost" 21 | ] 22 | } 23 | ], 24 | "handle": [ 25 | { 26 | "handler": "subroute", 27 | "routes": [ 28 | { 29 | "handle": [ 30 | { 31 | "body": "hello from localhost", 32 | "handler": "static_response", 33 | "status_code": 200 34 | } 35 | ], 36 | "match": [ 37 | { 38 | "path": [ 39 | "/version" 40 | ] 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | ], 47 | "terminal": true 48 | } 49 | ], 50 | "automatic_https": { 51 | "skip": [ 52 | "a.caddy.localhost" 53 | ] 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/http_valid_directive_like_site_address.caddyfiletest: -------------------------------------------------------------------------------- 1 | http://handle { 2 | file_server 3 | } 4 | ---------- 5 | { 6 | "apps": { 7 | "http": { 8 | "servers": { 9 | "srv0": { 10 | "listen": [ 11 | ":80" 12 | ], 13 | "routes": [ 14 | { 15 | "match": [ 16 | { 17 | "host": [ 18 | "handle" 19 | ] 20 | } 21 | ], 22 | "handle": [ 23 | { 24 | "handler": "subroute", 25 | "routes": [ 26 | { 27 | "handle": [ 28 | { 29 | "handler": "file_server", 30 | "hide": [ 31 | "./Caddyfile" 32 | ] 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | ], 39 | "terminal": true 40 | } 41 | ] 42 | } 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/https_on_domain.caddyfiletest: -------------------------------------------------------------------------------- 1 | a.caddy.localhost { 2 | respond /version 200 { 3 | body "hello from localhost" 4 | } 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":443" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "host": [ 20 | "a.caddy.localhost" 21 | ] 22 | } 23 | ], 24 | "handle": [ 25 | { 26 | "handler": "subroute", 27 | "routes": [ 28 | { 29 | "handle": [ 30 | { 31 | "body": "hello from localhost", 32 | "handler": "static_response", 33 | "status_code": 200 34 | } 35 | ], 36 | "match": [ 37 | { 38 | "path": [ 39 | "/version" 40 | ] 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | ], 47 | "terminal": true 48 | } 49 | ] 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/import_args_file.caddyfiletest: -------------------------------------------------------------------------------- 1 | example.com 2 | 3 | import testdata/import_respond.txt Groot Rocket 4 | import testdata/import_respond.txt you "the confused man" 5 | ---------- 6 | { 7 | "apps": { 8 | "http": { 9 | "servers": { 10 | "srv0": { 11 | "listen": [ 12 | ":443" 13 | ], 14 | "routes": [ 15 | { 16 | "match": [ 17 | { 18 | "host": [ 19 | "example.com" 20 | ] 21 | } 22 | ], 23 | "handle": [ 24 | { 25 | "handler": "subroute", 26 | "routes": [ 27 | { 28 | "handle": [ 29 | { 30 | "body": "'I am Groot', hears Rocket", 31 | "handler": "static_response" 32 | }, 33 | { 34 | "body": "'I am you', hears the confused man", 35 | "handler": "static_response" 36 | } 37 | ] 38 | } 39 | ] 40 | } 41 | ], 42 | "terminal": true 43 | } 44 | ] 45 | } 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/import_args_snippet.caddyfiletest: -------------------------------------------------------------------------------- 1 | (logging) { 2 | log { 3 | output file /var/log/caddy/{args[0]}.access.log 4 | } 5 | } 6 | 7 | a.example.com { 8 | import logging a.example.com 9 | } 10 | 11 | b.example.com { 12 | import logging b.example.com 13 | } 14 | ---------- 15 | { 16 | "logging": { 17 | "logs": { 18 | "default": { 19 | "exclude": [ 20 | "http.log.access.log0", 21 | "http.log.access.log1" 22 | ] 23 | }, 24 | "log0": { 25 | "writer": { 26 | "filename": "/var/log/caddy/a.example.com.access.log", 27 | "output": "file" 28 | }, 29 | "include": [ 30 | "http.log.access.log0" 31 | ] 32 | }, 33 | "log1": { 34 | "writer": { 35 | "filename": "/var/log/caddy/b.example.com.access.log", 36 | "output": "file" 37 | }, 38 | "include": [ 39 | "http.log.access.log1" 40 | ] 41 | } 42 | } 43 | }, 44 | "apps": { 45 | "http": { 46 | "servers": { 47 | "srv0": { 48 | "listen": [ 49 | ":443" 50 | ], 51 | "routes": [ 52 | { 53 | "match": [ 54 | { 55 | "host": [ 56 | "a.example.com" 57 | ] 58 | } 59 | ], 60 | "terminal": true 61 | }, 62 | { 63 | "match": [ 64 | { 65 | "host": [ 66 | "b.example.com" 67 | ] 68 | } 69 | ], 70 | "terminal": true 71 | } 72 | ], 73 | "logs": { 74 | "logger_names": { 75 | "a.example.com": [ 76 | "log0" 77 | ], 78 | "b.example.com": [ 79 | "log1" 80 | ] 81 | } 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/import_args_snippet_env_placeholder.caddyfiletest: -------------------------------------------------------------------------------- 1 | (foo) { 2 | respond {env.FOO} 3 | } 4 | 5 | :80 { 6 | import foo 7 | } 8 | ---------- 9 | { 10 | "apps": { 11 | "http": { 12 | "servers": { 13 | "srv0": { 14 | "listen": [ 15 | ":80" 16 | ], 17 | "routes": [ 18 | { 19 | "handle": [ 20 | { 21 | "body": "{env.FOO}", 22 | "handler": "static_response" 23 | } 24 | ] 25 | } 26 | ] 27 | } 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/import_block_snippet.caddyfiletest: -------------------------------------------------------------------------------- 1 | (snippet) { 2 | header { 3 | {block} 4 | } 5 | } 6 | 7 | example.com { 8 | import snippet { 9 | foo bar 10 | } 11 | } 12 | ---------- 13 | { 14 | "apps": { 15 | "http": { 16 | "servers": { 17 | "srv0": { 18 | "listen": [ 19 | ":443" 20 | ], 21 | "routes": [ 22 | { 23 | "match": [ 24 | { 25 | "host": [ 26 | "example.com" 27 | ] 28 | } 29 | ], 30 | "handle": [ 31 | { 32 | "handler": "subroute", 33 | "routes": [ 34 | { 35 | "handle": [ 36 | { 37 | "handler": "headers", 38 | "response": { 39 | "set": { 40 | "Foo": [ 41 | "bar" 42 | ] 43 | } 44 | } 45 | } 46 | ] 47 | } 48 | ] 49 | } 50 | ], 51 | "terminal": true 52 | } 53 | ] 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/import_block_snippet_args.caddyfiletest: -------------------------------------------------------------------------------- 1 | (snippet) { 2 | {block} 3 | } 4 | 5 | example.com { 6 | import snippet { 7 | header foo bar 8 | } 9 | } 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":443" 18 | ], 19 | "routes": [ 20 | { 21 | "match": [ 22 | { 23 | "host": [ 24 | "example.com" 25 | ] 26 | } 27 | ], 28 | "handle": [ 29 | { 30 | "handler": "subroute", 31 | "routes": [ 32 | { 33 | "handle": [ 34 | { 35 | "handler": "headers", 36 | "response": { 37 | "set": { 38 | "Foo": [ 39 | "bar" 40 | ] 41 | } 42 | } 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | ], 49 | "terminal": true 50 | } 51 | ] 52 | } 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/import_blocks_snippet.caddyfiletest: -------------------------------------------------------------------------------- 1 | (snippet) { 2 | header { 3 | {blocks.foo} 4 | } 5 | header { 6 | {blocks.bar} 7 | } 8 | } 9 | 10 | example.com { 11 | import snippet { 12 | foo { 13 | foo a 14 | } 15 | bar { 16 | bar b 17 | } 18 | } 19 | } 20 | ---------- 21 | { 22 | "apps": { 23 | "http": { 24 | "servers": { 25 | "srv0": { 26 | "listen": [ 27 | ":443" 28 | ], 29 | "routes": [ 30 | { 31 | "match": [ 32 | { 33 | "host": [ 34 | "example.com" 35 | ] 36 | } 37 | ], 38 | "handle": [ 39 | { 40 | "handler": "subroute", 41 | "routes": [ 42 | { 43 | "handle": [ 44 | { 45 | "handler": "headers", 46 | "response": { 47 | "set": { 48 | "Foo": [ 49 | "a" 50 | ] 51 | } 52 | } 53 | }, 54 | { 55 | "handler": "headers", 56 | "response": { 57 | "set": { 58 | "Bar": [ 59 | "b" 60 | ] 61 | } 62 | } 63 | } 64 | ] 65 | } 66 | ] 67 | } 68 | ], 69 | "terminal": true 70 | } 71 | ] 72 | } 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/import_blocks_snippet_nested.caddyfiletest: -------------------------------------------------------------------------------- 1 | (snippet) { 2 | header { 3 | {blocks.bar} 4 | } 5 | import sub_snippet { 6 | bar { 7 | {blocks.foo} 8 | } 9 | } 10 | } 11 | (sub_snippet) { 12 | header { 13 | {blocks.bar} 14 | } 15 | } 16 | example.com { 17 | import snippet { 18 | foo { 19 | foo a 20 | } 21 | bar { 22 | bar b 23 | } 24 | } 25 | } 26 | ---------- 27 | { 28 | "apps": { 29 | "http": { 30 | "servers": { 31 | "srv0": { 32 | "listen": [ 33 | ":443" 34 | ], 35 | "routes": [ 36 | { 37 | "match": [ 38 | { 39 | "host": [ 40 | "example.com" 41 | ] 42 | } 43 | ], 44 | "handle": [ 45 | { 46 | "handler": "subroute", 47 | "routes": [ 48 | { 49 | "handle": [ 50 | { 51 | "handler": "headers", 52 | "response": { 53 | "set": { 54 | "Bar": [ 55 | "b" 56 | ] 57 | } 58 | } 59 | }, 60 | { 61 | "handler": "headers", 62 | "response": { 63 | "set": { 64 | "Foo": [ 65 | "a" 66 | ] 67 | } 68 | } 69 | } 70 | ] 71 | } 72 | ] 73 | } 74 | ], 75 | "terminal": true 76 | } 77 | ] 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/log_add.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 { 2 | log 3 | 4 | vars foo foo 5 | 6 | log_append const bar 7 | log_append vars foo 8 | log_append placeholder {path} 9 | 10 | log_append /only-for-this-path secret value 11 | } 12 | ---------- 13 | { 14 | "apps": { 15 | "http": { 16 | "servers": { 17 | "srv0": { 18 | "listen": [ 19 | ":80" 20 | ], 21 | "routes": [ 22 | { 23 | "handle": [ 24 | { 25 | "foo": "foo", 26 | "handler": "vars" 27 | } 28 | ] 29 | }, 30 | { 31 | "match": [ 32 | { 33 | "path": [ 34 | "/only-for-this-path" 35 | ] 36 | } 37 | ], 38 | "handle": [ 39 | { 40 | "handler": "log_append", 41 | "key": "secret", 42 | "value": "value" 43 | } 44 | ] 45 | }, 46 | { 47 | "handle": [ 48 | { 49 | "handler": "log_append", 50 | "key": "const", 51 | "value": "bar" 52 | }, 53 | { 54 | "handler": "log_append", 55 | "key": "vars", 56 | "value": "foo" 57 | }, 58 | { 59 | "handler": "log_append", 60 | "key": "placeholder", 61 | "value": "{http.request.uri.path}" 62 | } 63 | ] 64 | } 65 | ], 66 | "logs": {} 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/log_append_encoder.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | log { 3 | format append { 4 | wrap json 5 | fields { 6 | wrap "foo" 7 | } 8 | env {env.EXAMPLE} 9 | int 1 10 | float 1.1 11 | bool true 12 | string "string" 13 | } 14 | } 15 | } 16 | 17 | :80 { 18 | respond "Hello, World!" 19 | } 20 | ---------- 21 | { 22 | "logging": { 23 | "logs": { 24 | "default": { 25 | "encoder": { 26 | "fields": { 27 | "bool": true, 28 | "env": "{env.EXAMPLE}", 29 | "float": 1.1, 30 | "int": 1, 31 | "string": "string", 32 | "wrap": "foo" 33 | }, 34 | "format": "append", 35 | "wrap": { 36 | "format": "json" 37 | } 38 | } 39 | } 40 | } 41 | }, 42 | "apps": { 43 | "http": { 44 | "servers": { 45 | "srv0": { 46 | "listen": [ 47 | ":80" 48 | ], 49 | "routes": [ 50 | { 51 | "handle": [ 52 | { 53 | "body": "Hello, World!", 54 | "handler": "static_response" 55 | } 56 | ] 57 | } 58 | ] 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/log_filter_no_wrap.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | log { 4 | output stdout 5 | format filter { 6 | fields { 7 | request>headers>Server delete 8 | } 9 | } 10 | } 11 | ---------- 12 | { 13 | "logging": { 14 | "logs": { 15 | "default": { 16 | "exclude": [ 17 | "http.log.access.log0" 18 | ] 19 | }, 20 | "log0": { 21 | "writer": { 22 | "output": "stdout" 23 | }, 24 | "encoder": { 25 | "fields": { 26 | "request\u003eheaders\u003eServer": { 27 | "filter": "delete" 28 | } 29 | }, 30 | "format": "filter" 31 | }, 32 | "include": [ 33 | "http.log.access.log0" 34 | ] 35 | } 36 | } 37 | }, 38 | "apps": { 39 | "http": { 40 | "servers": { 41 | "srv0": { 42 | "listen": [ 43 | ":80" 44 | ], 45 | "logs": { 46 | "default_logger_name": "log0" 47 | } 48 | } 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/log_override_name_multiaccess.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | log access-console { 3 | include http.log.access.foo 4 | output file access-localhost.log 5 | format console 6 | } 7 | 8 | log access-json { 9 | include http.log.access.foo 10 | output file access-localhost.json 11 | format json 12 | } 13 | } 14 | 15 | http://localhost:8881 { 16 | log foo 17 | } 18 | ---------- 19 | { 20 | "logging": { 21 | "logs": { 22 | "access-console": { 23 | "writer": { 24 | "filename": "access-localhost.log", 25 | "output": "file" 26 | }, 27 | "encoder": { 28 | "format": "console" 29 | }, 30 | "include": [ 31 | "http.log.access.foo" 32 | ] 33 | }, 34 | "access-json": { 35 | "writer": { 36 | "filename": "access-localhost.json", 37 | "output": "file" 38 | }, 39 | "encoder": { 40 | "format": "json" 41 | }, 42 | "include": [ 43 | "http.log.access.foo" 44 | ] 45 | }, 46 | "default": { 47 | "exclude": [ 48 | "http.log.access.foo" 49 | ] 50 | } 51 | } 52 | }, 53 | "apps": { 54 | "http": { 55 | "servers": { 56 | "srv0": { 57 | "listen": [ 58 | ":8881" 59 | ], 60 | "routes": [ 61 | { 62 | "match": [ 63 | { 64 | "host": [ 65 | "localhost" 66 | ] 67 | } 68 | ], 69 | "terminal": true 70 | } 71 | ], 72 | "automatic_https": { 73 | "skip": [ 74 | "localhost" 75 | ] 76 | }, 77 | "logs": { 78 | "logger_names": { 79 | "localhost": [ 80 | "foo" 81 | ] 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/log_override_name_multiaccess_debug.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | debug 3 | 4 | log access-console { 5 | include http.log.access.foo 6 | output file access-localhost.log 7 | format console 8 | } 9 | 10 | log access-json { 11 | include http.log.access.foo 12 | output file access-localhost.json 13 | format json 14 | } 15 | } 16 | 17 | http://localhost:8881 { 18 | log foo 19 | } 20 | ---------- 21 | { 22 | "logging": { 23 | "logs": { 24 | "access-console": { 25 | "writer": { 26 | "filename": "access-localhost.log", 27 | "output": "file" 28 | }, 29 | "encoder": { 30 | "format": "console" 31 | }, 32 | "level": "DEBUG", 33 | "include": [ 34 | "http.log.access.foo" 35 | ] 36 | }, 37 | "access-json": { 38 | "writer": { 39 | "filename": "access-localhost.json", 40 | "output": "file" 41 | }, 42 | "encoder": { 43 | "format": "json" 44 | }, 45 | "level": "DEBUG", 46 | "include": [ 47 | "http.log.access.foo" 48 | ] 49 | }, 50 | "default": { 51 | "level": "DEBUG", 52 | "exclude": [ 53 | "http.log.access.foo" 54 | ] 55 | } 56 | } 57 | }, 58 | "apps": { 59 | "http": { 60 | "servers": { 61 | "srv0": { 62 | "listen": [ 63 | ":8881" 64 | ], 65 | "routes": [ 66 | { 67 | "match": [ 68 | { 69 | "host": [ 70 | "localhost" 71 | ] 72 | } 73 | ], 74 | "terminal": true 75 | } 76 | ], 77 | "automatic_https": { 78 | "skip": [ 79 | "localhost" 80 | ] 81 | }, 82 | "logs": { 83 | "logger_names": { 84 | "localhost": [ 85 | "foo" 86 | ] 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/log_roll_days.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | log { 4 | output file /var/log/access.log { 5 | roll_size 1gb 6 | roll_uncompressed 7 | roll_local_time 8 | roll_keep 5 9 | roll_keep_for 90d 10 | } 11 | } 12 | ---------- 13 | { 14 | "logging": { 15 | "logs": { 16 | "default": { 17 | "exclude": [ 18 | "http.log.access.log0" 19 | ] 20 | }, 21 | "log0": { 22 | "writer": { 23 | "filename": "/var/log/access.log", 24 | "output": "file", 25 | "roll_gzip": false, 26 | "roll_keep": 5, 27 | "roll_keep_days": 90, 28 | "roll_local_time": true, 29 | "roll_size_mb": 954 30 | }, 31 | "include": [ 32 | "http.log.access.log0" 33 | ] 34 | } 35 | } 36 | }, 37 | "apps": { 38 | "http": { 39 | "servers": { 40 | "srv0": { 41 | "listen": [ 42 | ":80" 43 | ], 44 | "logs": { 45 | "default_logger_name": "log0" 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/log_sampling.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 { 2 | log { 3 | sampling { 4 | interval 300 5 | first 50 6 | thereafter 40 7 | } 8 | } 9 | } 10 | ---------- 11 | { 12 | "logging": { 13 | "logs": { 14 | "default": { 15 | "exclude": [ 16 | "http.log.access.log0" 17 | ] 18 | }, 19 | "log0": { 20 | "sampling": { 21 | "interval": 300, 22 | "first": 50, 23 | "thereafter": 40 24 | }, 25 | "include": [ 26 | "http.log.access.log0" 27 | ] 28 | } 29 | } 30 | }, 31 | "apps": { 32 | "http": { 33 | "servers": { 34 | "srv0": { 35 | "listen": [ 36 | ":80" 37 | ], 38 | "logs": { 39 | "default_logger_name": "log0" 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/log_skip_hosts.caddyfiletest: -------------------------------------------------------------------------------- 1 | one.example.com { 2 | log 3 | } 4 | 5 | two.example.com { 6 | } 7 | 8 | three.example.com { 9 | } 10 | 11 | example.com { 12 | } 13 | ---------- 14 | { 15 | "apps": { 16 | "http": { 17 | "servers": { 18 | "srv0": { 19 | "listen": [ 20 | ":443" 21 | ], 22 | "routes": [ 23 | { 24 | "match": [ 25 | { 26 | "host": [ 27 | "three.example.com" 28 | ] 29 | } 30 | ], 31 | "terminal": true 32 | }, 33 | { 34 | "match": [ 35 | { 36 | "host": [ 37 | "one.example.com" 38 | ] 39 | } 40 | ], 41 | "terminal": true 42 | }, 43 | { 44 | "match": [ 45 | { 46 | "host": [ 47 | "two.example.com" 48 | ] 49 | } 50 | ], 51 | "terminal": true 52 | }, 53 | { 54 | "match": [ 55 | { 56 | "host": [ 57 | "example.com" 58 | ] 59 | } 60 | ], 61 | "terminal": true 62 | } 63 | ], 64 | "logs": { 65 | "logger_names": { 66 | "one.example.com": [ 67 | "" 68 | ] 69 | }, 70 | "skip_hosts": [ 71 | "example.com", 72 | "three.example.com", 73 | "two.example.com" 74 | ] 75 | } 76 | } 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/matchers_in_route.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 { 2 | route { 3 | # unused matchers should not panic 4 | # see https://github.com/caddyserver/caddy/issues/3745 5 | @matcher1 path /path1 6 | @matcher2 path /path2 7 | } 8 | } 9 | ---------- 10 | { 11 | "apps": { 12 | "http": { 13 | "servers": { 14 | "srv0": { 15 | "listen": [ 16 | ":80" 17 | ], 18 | "routes": [ 19 | { 20 | "handle": [ 21 | { 22 | "handler": "subroute" 23 | } 24 | ] 25 | } 26 | ] 27 | } 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/method_directive.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8080 { 2 | method FOO 3 | } 4 | ---------- 5 | { 6 | "apps": { 7 | "http": { 8 | "servers": { 9 | "srv0": { 10 | "listen": [ 11 | ":8080" 12 | ], 13 | "routes": [ 14 | { 15 | "handle": [ 16 | { 17 | "handler": "rewrite", 18 | "method": "FOO" 19 | } 20 | ] 21 | } 22 | ] 23 | } 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/metrics_disable_om.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 { 2 | metrics /metrics { 3 | disable_openmetrics 4 | } 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":80" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "path": [ 20 | "/metrics" 21 | ] 22 | } 23 | ], 24 | "handle": [ 25 | { 26 | "disable_openmetrics": true, 27 | "handler": "metrics" 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/metrics_merge_options.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | metrics 3 | servers :80 { 4 | metrics { 5 | per_host 6 | } 7 | } 8 | } 9 | :80 { 10 | respond "Hello" 11 | } 12 | 13 | ---------- 14 | { 15 | "apps": { 16 | "http": { 17 | "servers": { 18 | "srv0": { 19 | "listen": [ 20 | ":80" 21 | ], 22 | "routes": [ 23 | { 24 | "handle": [ 25 | { 26 | "body": "Hello", 27 | "handler": "static_response" 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | }, 34 | "metrics": { 35 | "per_host": true 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/metrics_perhost.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | servers :80 { 3 | metrics { 4 | per_host 5 | } 6 | } 7 | } 8 | :80 { 9 | respond "Hello" 10 | } 11 | ---------- 12 | { 13 | "apps": { 14 | "http": { 15 | "servers": { 16 | "srv0": { 17 | "listen": [ 18 | ":80" 19 | ], 20 | "routes": [ 21 | { 22 | "handle": [ 23 | { 24 | "body": "Hello", 25 | "handler": "static_response" 26 | } 27 | ] 28 | } 29 | ] 30 | } 31 | }, 32 | "metrics": { 33 | "per_host": true 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/metrics_syntax.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 { 2 | metrics /metrics 3 | } 4 | ---------- 5 | { 6 | "apps": { 7 | "http": { 8 | "servers": { 9 | "srv0": { 10 | "listen": [ 11 | ":80" 12 | ], 13 | "routes": [ 14 | { 15 | "match": [ 16 | { 17 | "path": [ 18 | "/metrics" 19 | ] 20 | } 21 | ], 22 | "handle": [ 23 | { 24 | "handler": "metrics" 25 | } 26 | ] 27 | } 28 | ] 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/not_block_merging.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | @test { 4 | not { 5 | header Abc "123" 6 | header Bcd "123" 7 | } 8 | } 9 | respond @test 403 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":80" 18 | ], 19 | "routes": [ 20 | { 21 | "match": [ 22 | { 23 | "not": [ 24 | { 25 | "header": { 26 | "Abc": [ 27 | "123" 28 | ], 29 | "Bcd": [ 30 | "123" 31 | ] 32 | } 33 | } 34 | ] 35 | } 36 | ], 37 | "handle": [ 38 | { 39 | "handler": "static_response", 40 | "status_code": 403 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/php_fastcgi_index_off.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8884 2 | 3 | php_fastcgi localhost:9000 { 4 | # some php_fastcgi-specific subdirectives 5 | split .php .php5 6 | env VAR1 value1 7 | env VAR2 value2 8 | root /var/www 9 | index off 10 | dial_timeout 3s 11 | read_timeout 10s 12 | write_timeout 20s 13 | 14 | # passed through to reverse_proxy (directive order doesn't matter!) 15 | lb_policy random 16 | } 17 | ---------- 18 | { 19 | "apps": { 20 | "http": { 21 | "servers": { 22 | "srv0": { 23 | "listen": [ 24 | ":8884" 25 | ], 26 | "routes": [ 27 | { 28 | "match": [ 29 | { 30 | "path": [ 31 | "*.php", 32 | "*.php5" 33 | ] 34 | } 35 | ], 36 | "handle": [ 37 | { 38 | "handler": "reverse_proxy", 39 | "load_balancing": { 40 | "selection_policy": { 41 | "policy": "random" 42 | } 43 | }, 44 | "transport": { 45 | "dial_timeout": 3000000000, 46 | "env": { 47 | "VAR1": "value1", 48 | "VAR2": "value2" 49 | }, 50 | "protocol": "fastcgi", 51 | "read_timeout": 10000000000, 52 | "root": "/var/www", 53 | "split_path": [ 54 | ".php", 55 | ".php5" 56 | ], 57 | "write_timeout": 20000000000 58 | }, 59 | "upstreams": [ 60 | { 61 | "dial": "localhost:9000" 62 | } 63 | ] 64 | } 65 | ] 66 | } 67 | ] 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/push.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | push * /foo.txt 4 | 5 | push { 6 | GET /foo.txt 7 | } 8 | 9 | push { 10 | GET /foo.txt 11 | HEAD /foo.txt 12 | } 13 | 14 | push { 15 | headers { 16 | Foo bar 17 | } 18 | } 19 | ---------- 20 | { 21 | "apps": { 22 | "http": { 23 | "servers": { 24 | "srv0": { 25 | "listen": [ 26 | ":80" 27 | ], 28 | "routes": [ 29 | { 30 | "handle": [ 31 | { 32 | "handler": "push", 33 | "resources": [ 34 | { 35 | "target": "/foo.txt" 36 | } 37 | ] 38 | }, 39 | { 40 | "handler": "push", 41 | "resources": [ 42 | { 43 | "method": "GET", 44 | "target": "/foo.txt" 45 | } 46 | ] 47 | }, 48 | { 49 | "handler": "push", 50 | "resources": [ 51 | { 52 | "method": "GET", 53 | "target": "/foo.txt" 54 | }, 55 | { 56 | "method": "HEAD", 57 | "target": "/foo.txt" 58 | } 59 | ] 60 | }, 61 | { 62 | "handler": "push", 63 | "headers": { 64 | "set": { 65 | "Foo": [ 66 | "bar" 67 | ] 68 | } 69 | } 70 | } 71 | ] 72 | } 73 | ] 74 | } 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/request_body.caddyfiletest: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | request_body { 4 | max_size 1MB 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":443" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "host": [ 20 | "localhost" 21 | ] 22 | } 23 | ], 24 | "handle": [ 25 | { 26 | "handler": "subroute", 27 | "routes": [ 28 | { 29 | "handle": [ 30 | { 31 | "handler": "request_body", 32 | "max_size": 1000000 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | ], 39 | "terminal": true 40 | } 41 | ] 42 | } 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/request_header.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | @matcher path /something* 4 | request_header @matcher Denis "Ritchie" 5 | 6 | request_header +Edsger "Dijkstra" 7 | request_header -Wolfram 8 | 9 | @images path /images/* 10 | request_header @images Cache-Control "public, max-age=3600, stale-while-revalidate=86400" 11 | ---------- 12 | { 13 | "apps": { 14 | "http": { 15 | "servers": { 16 | "srv0": { 17 | "listen": [ 18 | ":80" 19 | ], 20 | "routes": [ 21 | { 22 | "match": [ 23 | { 24 | "path": [ 25 | "/something*" 26 | ] 27 | } 28 | ], 29 | "handle": [ 30 | { 31 | "handler": "headers", 32 | "request": { 33 | "set": { 34 | "Denis": [ 35 | "Ritchie" 36 | ] 37 | } 38 | } 39 | } 40 | ] 41 | }, 42 | { 43 | "match": [ 44 | { 45 | "path": [ 46 | "/images/*" 47 | ] 48 | } 49 | ], 50 | "handle": [ 51 | { 52 | "handler": "headers", 53 | "request": { 54 | "set": { 55 | "Cache-Control": [ 56 | "public, max-age=3600, stale-while-revalidate=86400" 57 | ] 58 | } 59 | } 60 | } 61 | ] 62 | }, 63 | { 64 | "handle": [ 65 | { 66 | "handler": "headers", 67 | "request": { 68 | "add": { 69 | "Edsger": [ 70 | "Dijkstra" 71 | ] 72 | } 73 | } 74 | }, 75 | { 76 | "handler": "headers", 77 | "request": { 78 | "delete": [ 79 | "Wolfram" 80 | ] 81 | } 82 | } 83 | ] 84 | } 85 | ] 86 | } 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_buffers.caddyfiletest: -------------------------------------------------------------------------------- 1 | https://example.com { 2 | reverse_proxy https://localhost:54321 { 3 | request_buffers unlimited 4 | response_buffers unlimited 5 | } 6 | } 7 | 8 | ---------- 9 | { 10 | "apps": { 11 | "http": { 12 | "servers": { 13 | "srv0": { 14 | "listen": [ 15 | ":443" 16 | ], 17 | "routes": [ 18 | { 19 | "match": [ 20 | { 21 | "host": [ 22 | "example.com" 23 | ] 24 | } 25 | ], 26 | "handle": [ 27 | { 28 | "handler": "subroute", 29 | "routes": [ 30 | { 31 | "handle": [ 32 | { 33 | "handler": "reverse_proxy", 34 | "request_buffers": -1, 35 | "response_buffers": -1, 36 | "transport": { 37 | "protocol": "http", 38 | "tls": {} 39 | }, 40 | "upstreams": [ 41 | { 42 | "dial": "localhost:54321" 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | ] 49 | } 50 | ], 51 | "terminal": true 52 | } 53 | ] 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_dynamic_upstreams_grace_period.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8884 { 2 | reverse_proxy { 3 | dynamic srv { 4 | name foo 5 | refresh 5m 6 | grace_period 5s 7 | } 8 | } 9 | } 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":8884" 18 | ], 19 | "routes": [ 20 | { 21 | "handle": [ 22 | { 23 | "dynamic_upstreams": { 24 | "grace_period": 5000000000, 25 | "name": "foo", 26 | "refresh": 300000000000, 27 | "source": "srv" 28 | }, 29 | "handler": "reverse_proxy" 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_empty_non_http_transport.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8884 2 | 3 | reverse_proxy 127.0.0.1:65535 { 4 | transport fastcgi 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":8884" 14 | ], 15 | "routes": [ 16 | { 17 | "handle": [ 18 | { 19 | "handler": "reverse_proxy", 20 | "transport": { 21 | "protocol": "fastcgi" 22 | }, 23 | "upstreams": [ 24 | { 25 | "dial": "127.0.0.1:65535" 26 | } 27 | ] 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_h2c_shorthand.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8884 2 | 3 | reverse_proxy h2c://localhost:8080 4 | 5 | reverse_proxy unix+h2c//run/app.sock 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":8884" 14 | ], 15 | "routes": [ 16 | { 17 | "handle": [ 18 | { 19 | "handler": "reverse_proxy", 20 | "transport": { 21 | "protocol": "http", 22 | "versions": [ 23 | "h2c", 24 | "2" 25 | ] 26 | }, 27 | "upstreams": [ 28 | { 29 | "dial": "localhost:8080" 30 | } 31 | ] 32 | }, 33 | { 34 | "handler": "reverse_proxy", 35 | "transport": { 36 | "protocol": "http", 37 | "versions": [ 38 | "h2c", 39 | "2" 40 | ] 41 | }, 42 | "upstreams": [ 43 | { 44 | "dial": "unix//run/app.sock" 45 | } 46 | ] 47 | } 48 | ] 49 | } 50 | ] 51 | } 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_health_headers.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8884 2 | 3 | reverse_proxy 127.0.0.1:65535 { 4 | health_headers { 5 | Host example.com 6 | X-Header-Key 95ca39e3cbe7 7 | X-Header-Keys VbG4NZwWnipo 335Q9/MhqcNU3s2TO 8 | X-Empty-Value 9 | Same-Key 1 10 | Same-Key 2 11 | X-System-Hostname {system.hostname} 12 | } 13 | health_uri /health 14 | } 15 | ---------- 16 | { 17 | "apps": { 18 | "http": { 19 | "servers": { 20 | "srv0": { 21 | "listen": [ 22 | ":8884" 23 | ], 24 | "routes": [ 25 | { 26 | "handle": [ 27 | { 28 | "handler": "reverse_proxy", 29 | "health_checks": { 30 | "active": { 31 | "headers": { 32 | "Host": [ 33 | "example.com" 34 | ], 35 | "Same-Key": [ 36 | "1", 37 | "2" 38 | ], 39 | "X-Empty-Value": [ 40 | "" 41 | ], 42 | "X-Header-Key": [ 43 | "95ca39e3cbe7" 44 | ], 45 | "X-Header-Keys": [ 46 | "VbG4NZwWnipo", 47 | "335Q9/MhqcNU3s2TO" 48 | ], 49 | "X-System-Hostname": [ 50 | "{system.hostname}" 51 | ] 52 | }, 53 | "uri": "/health" 54 | } 55 | }, 56 | "upstreams": [ 57 | { 58 | "dial": "127.0.0.1:65535" 59 | } 60 | ] 61 | } 62 | ] 63 | } 64 | ] 65 | } 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_health_method.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8884 2 | 3 | reverse_proxy 127.0.0.1:65535 { 4 | health_uri /health 5 | health_method HEAD 6 | } 7 | ---------- 8 | { 9 | "apps": { 10 | "http": { 11 | "servers": { 12 | "srv0": { 13 | "listen": [ 14 | ":8884" 15 | ], 16 | "routes": [ 17 | { 18 | "handle": [ 19 | { 20 | "handler": "reverse_proxy", 21 | "health_checks": { 22 | "active": { 23 | "method": "HEAD", 24 | "uri": "/health" 25 | } 26 | }, 27 | "upstreams": [ 28 | { 29 | "dial": "127.0.0.1:65535" 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_health_path_query.caddyfiletest: -------------------------------------------------------------------------------- 1 | # Health with query in the uri 2 | :8443 { 3 | reverse_proxy localhost:54321 { 4 | health_uri /health?ready=1 5 | health_status 2xx 6 | } 7 | } 8 | 9 | # Health without query in the uri 10 | :8444 { 11 | reverse_proxy localhost:54321 { 12 | health_uri /health 13 | health_status 200 14 | } 15 | } 16 | 17 | ---------- 18 | { 19 | "apps": { 20 | "http": { 21 | "servers": { 22 | "srv0": { 23 | "listen": [ 24 | ":8443" 25 | ], 26 | "routes": [ 27 | { 28 | "handle": [ 29 | { 30 | "handler": "reverse_proxy", 31 | "health_checks": { 32 | "active": { 33 | "expect_status": 2, 34 | "uri": "/health?ready=1" 35 | } 36 | }, 37 | "upstreams": [ 38 | { 39 | "dial": "localhost:54321" 40 | } 41 | ] 42 | } 43 | ] 44 | } 45 | ] 46 | }, 47 | "srv1": { 48 | "listen": [ 49 | ":8444" 50 | ], 51 | "routes": [ 52 | { 53 | "handle": [ 54 | { 55 | "handler": "reverse_proxy", 56 | "health_checks": { 57 | "active": { 58 | "expect_status": 200, 59 | "uri": "/health" 60 | } 61 | }, 62 | "upstreams": [ 63 | { 64 | "dial": "localhost:54321" 65 | } 66 | ] 67 | } 68 | ] 69 | } 70 | ] 71 | } 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_health_reqbody.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8884 2 | 3 | reverse_proxy 127.0.0.1:65535 { 4 | health_uri /health 5 | health_request_body "test body" 6 | } 7 | ---------- 8 | { 9 | "apps": { 10 | "http": { 11 | "servers": { 12 | "srv0": { 13 | "listen": [ 14 | ":8884" 15 | ], 16 | "routes": [ 17 | { 18 | "handle": [ 19 | { 20 | "handler": "reverse_proxy", 21 | "health_checks": { 22 | "active": { 23 | "body": "test body", 24 | "uri": "/health" 25 | } 26 | }, 27 | "upstreams": [ 28 | { 29 | "dial": "127.0.0.1:65535" 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_http_transport_forward_proxy_url.txt: -------------------------------------------------------------------------------- 1 | :8884 2 | reverse_proxy 127.0.0.1:65535 { 3 | transport http { 4 | forward_proxy_url http://localhost:8080 5 | } 6 | } 7 | ---------- 8 | { 9 | "apps": { 10 | "http": { 11 | "servers": { 12 | "srv0": { 13 | "listen": [ 14 | ":8884" 15 | ], 16 | "routes": [ 17 | { 18 | "handle": [ 19 | { 20 | "handler": "reverse_proxy", 21 | "transport": { 22 | "network_proxy": { 23 | "from": "url", 24 | "url": "http://localhost:8080" 25 | }, 26 | "protocol": "http" 27 | }, 28 | "upstreams": [ 29 | { 30 | "dial": "127.0.0.1:65535" 31 | } 32 | ] 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_http_transport_none_proxy.txt: -------------------------------------------------------------------------------- 1 | :8884 2 | reverse_proxy 127.0.0.1:65535 { 3 | transport http { 4 | network_proxy none 5 | } 6 | } 7 | ---------- 8 | { 9 | "apps": { 10 | "http": { 11 | "servers": { 12 | "srv0": { 13 | "listen": [ 14 | ":8884" 15 | ], 16 | "routes": [ 17 | { 18 | "handle": [ 19 | { 20 | "handler": "reverse_proxy", 21 | "transport": { 22 | "network_proxy": { 23 | "from": "none" 24 | }, 25 | "protocol": "http" 26 | }, 27 | "upstreams": [ 28 | { 29 | "dial": "127.0.0.1:65535" 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_http_transport_tls_file_cert.txt: -------------------------------------------------------------------------------- 1 | :8884 2 | reverse_proxy 127.0.0.1:65535 { 3 | transport http { 4 | tls_trust_pool file { 5 | pem_file ../caddy.ca.cer 6 | } 7 | } 8 | } 9 | ---------- 10 | { 11 | "apps": { 12 | "http": { 13 | "servers": { 14 | "srv0": { 15 | "listen": [ 16 | ":8884" 17 | ], 18 | "routes": [ 19 | { 20 | "handle": [ 21 | { 22 | "handler": "reverse_proxy", 23 | "transport": { 24 | "protocol": "http", 25 | "tls": { 26 | "ca": { 27 | "pem_files": [ 28 | "../caddy.ca.cer" 29 | ], 30 | "provider": "file" 31 | } 32 | } 33 | }, 34 | "upstreams": [ 35 | { 36 | "dial": "127.0.0.1:65535" 37 | } 38 | ] 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_http_transport_url_proxy.txt: -------------------------------------------------------------------------------- 1 | :8884 2 | reverse_proxy 127.0.0.1:65535 { 3 | transport http { 4 | network_proxy url http://localhost:8080 5 | } 6 | } 7 | ---------- 8 | { 9 | "apps": { 10 | "http": { 11 | "servers": { 12 | "srv0": { 13 | "listen": [ 14 | ":8884" 15 | ], 16 | "routes": [ 17 | { 18 | "handle": [ 19 | { 20 | "handler": "reverse_proxy", 21 | "transport": { 22 | "network_proxy": { 23 | "from": "url", 24 | "url": "http://localhost:8080" 25 | }, 26 | "protocol": "http" 27 | }, 28 | "upstreams": [ 29 | { 30 | "dial": "127.0.0.1:65535" 31 | } 32 | ] 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_load_balance.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8884 2 | 3 | reverse_proxy 127.0.0.1:65535 { 4 | lb_policy first 5 | lb_retries 5 6 | lb_try_duration 10s 7 | lb_try_interval 500ms 8 | lb_retry_match { 9 | path /foo* 10 | method POST 11 | } 12 | lb_retry_match path /bar* 13 | } 14 | ---------- 15 | { 16 | "apps": { 17 | "http": { 18 | "servers": { 19 | "srv0": { 20 | "listen": [ 21 | ":8884" 22 | ], 23 | "routes": [ 24 | { 25 | "handle": [ 26 | { 27 | "handler": "reverse_proxy", 28 | "load_balancing": { 29 | "retries": 5, 30 | "retry_match": [ 31 | { 32 | "method": [ 33 | "POST" 34 | ], 35 | "path": [ 36 | "/foo*" 37 | ] 38 | }, 39 | { 40 | "path": [ 41 | "/bar*" 42 | ] 43 | } 44 | ], 45 | "selection_policy": { 46 | "policy": "first" 47 | }, 48 | "try_duration": 10000000000, 49 | "try_interval": 500000000 50 | }, 51 | "upstreams": [ 52 | { 53 | "dial": "127.0.0.1:65535" 54 | } 55 | ] 56 | } 57 | ] 58 | } 59 | ] 60 | } 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_load_balance_wrr.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8884 2 | 3 | reverse_proxy 127.0.0.1:65535 127.0.0.1:35535 { 4 | lb_policy weighted_round_robin 10 1 5 | lb_retries 5 6 | lb_try_duration 10s 7 | lb_try_interval 500ms 8 | lb_retry_match { 9 | path /foo* 10 | method POST 11 | } 12 | lb_retry_match path /bar* 13 | } 14 | ---------- 15 | { 16 | "apps": { 17 | "http": { 18 | "servers": { 19 | "srv0": { 20 | "listen": [ 21 | ":8884" 22 | ], 23 | "routes": [ 24 | { 25 | "handle": [ 26 | { 27 | "handler": "reverse_proxy", 28 | "load_balancing": { 29 | "retries": 5, 30 | "retry_match": [ 31 | { 32 | "method": [ 33 | "POST" 34 | ], 35 | "path": [ 36 | "/foo*" 37 | ] 38 | }, 39 | { 40 | "path": [ 41 | "/bar*" 42 | ] 43 | } 44 | ], 45 | "selection_policy": { 46 | "policy": "weighted_round_robin", 47 | "weights": [ 48 | 10, 49 | 1 50 | ] 51 | }, 52 | "try_duration": 10000000000, 53 | "try_interval": 500000000 54 | }, 55 | "upstreams": [ 56 | { 57 | "dial": "127.0.0.1:65535" 58 | }, 59 | { 60 | "dial": "127.0.0.1:35535" 61 | } 62 | ] 63 | } 64 | ] 65 | } 66 | ] 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_localaddr.caddyfiletest: -------------------------------------------------------------------------------- 1 | https://example.com { 2 | reverse_proxy http://localhost:54321 { 3 | transport http { 4 | local_address 192.168.0.1 5 | } 6 | } 7 | } 8 | 9 | ---------- 10 | { 11 | "apps": { 12 | "http": { 13 | "servers": { 14 | "srv0": { 15 | "listen": [ 16 | ":443" 17 | ], 18 | "routes": [ 19 | { 20 | "match": [ 21 | { 22 | "host": [ 23 | "example.com" 24 | ] 25 | } 26 | ], 27 | "handle": [ 28 | { 29 | "handler": "subroute", 30 | "routes": [ 31 | { 32 | "handle": [ 33 | { 34 | "handler": "reverse_proxy", 35 | "transport": { 36 | "local_address": "192.168.0.1", 37 | "protocol": "http" 38 | }, 39 | "upstreams": [ 40 | { 41 | "dial": "localhost:54321" 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | ] 48 | } 49 | ], 50 | "terminal": true 51 | } 52 | ] 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_port_range.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8884 { 2 | # Port range 3 | reverse_proxy localhost:8001-8002 4 | 5 | # Port range with placeholder 6 | reverse_proxy {host}:8001-8002 7 | 8 | # Port range with scheme 9 | reverse_proxy https://localhost:8001-8002 10 | } 11 | ---------- 12 | { 13 | "apps": { 14 | "http": { 15 | "servers": { 16 | "srv0": { 17 | "listen": [ 18 | ":8884" 19 | ], 20 | "routes": [ 21 | { 22 | "handle": [ 23 | { 24 | "handler": "reverse_proxy", 25 | "upstreams": [ 26 | { 27 | "dial": "localhost:8001" 28 | }, 29 | { 30 | "dial": "localhost:8002" 31 | } 32 | ] 33 | }, 34 | { 35 | "handler": "reverse_proxy", 36 | "upstreams": [ 37 | { 38 | "dial": "{http.request.host}:8001" 39 | }, 40 | { 41 | "dial": "{http.request.host}:8002" 42 | } 43 | ] 44 | }, 45 | { 46 | "handler": "reverse_proxy", 47 | "transport": { 48 | "protocol": "http", 49 | "tls": {} 50 | }, 51 | "upstreams": [ 52 | { 53 | "dial": "localhost:8001" 54 | }, 55 | { 56 | "dial": "localhost:8002" 57 | } 58 | ] 59 | } 60 | ] 61 | } 62 | ] 63 | } 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/reverse_proxy_trusted_proxies.caddyfiletest: -------------------------------------------------------------------------------- 1 | :8884 2 | 3 | reverse_proxy 127.0.0.1:65535 { 4 | trusted_proxies 127.0.0.1 5 | } 6 | 7 | reverse_proxy 127.0.0.1:65535 { 8 | trusted_proxies private_ranges 9 | } 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":8884" 18 | ], 19 | "routes": [ 20 | { 21 | "handle": [ 22 | { 23 | "handler": "reverse_proxy", 24 | "trusted_proxies": [ 25 | "127.0.0.1" 26 | ], 27 | "upstreams": [ 28 | { 29 | "dial": "127.0.0.1:65535" 30 | } 31 | ] 32 | }, 33 | { 34 | "handler": "reverse_proxy", 35 | "trusted_proxies": [ 36 | "192.168.0.0/16", 37 | "172.16.0.0/12", 38 | "10.0.0.0/8", 39 | "127.0.0.1/8", 40 | "fd00::/8", 41 | "::1" 42 | ], 43 | "upstreams": [ 44 | { 45 | "dial": "127.0.0.1:65535" 46 | } 47 | ] 48 | } 49 | ] 50 | } 51 | ] 52 | } 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/server_names.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | servers :443 { 3 | name https 4 | } 5 | 6 | servers :8000 { 7 | name app1 8 | } 9 | 10 | servers :8001 { 11 | name app2 12 | } 13 | 14 | servers 123.123.123.123:8002 { 15 | name bind-server 16 | } 17 | } 18 | 19 | example.com { 20 | } 21 | 22 | :8000 { 23 | } 24 | 25 | :8001, :8002 { 26 | } 27 | 28 | :8002 { 29 | bind 123.123.123.123 222.222.222.222 30 | } 31 | ---------- 32 | { 33 | "apps": { 34 | "http": { 35 | "servers": { 36 | "app1": { 37 | "listen": [ 38 | ":8000" 39 | ] 40 | }, 41 | "app2": { 42 | "listen": [ 43 | ":8001" 44 | ] 45 | }, 46 | "bind-server": { 47 | "listen": [ 48 | "123.123.123.123:8002", 49 | "222.222.222.222:8002" 50 | ] 51 | }, 52 | "https": { 53 | "listen": [ 54 | ":443" 55 | ], 56 | "routes": [ 57 | { 58 | "match": [ 59 | { 60 | "host": [ 61 | "example.com" 62 | ] 63 | } 64 | ], 65 | "terminal": true 66 | } 67 | ] 68 | }, 69 | "srv4": { 70 | "listen": [ 71 | ":8002" 72 | ] 73 | } 74 | } 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/shorthand_parameterized_placeholders.caddyfiletest: -------------------------------------------------------------------------------- 1 | localhost:80 2 | 3 | respond * "{header.content-type} {labels.0} {query.p} {path.0} {re.name.0}" 4 | 5 | @match path_regexp ^/foo(.*)$ 6 | respond @match "{re.1}" 7 | ---------- 8 | { 9 | "apps": { 10 | "http": { 11 | "servers": { 12 | "srv0": { 13 | "listen": [ 14 | ":80" 15 | ], 16 | "routes": [ 17 | { 18 | "match": [ 19 | { 20 | "host": [ 21 | "localhost" 22 | ] 23 | } 24 | ], 25 | "handle": [ 26 | { 27 | "handler": "subroute", 28 | "routes": [ 29 | { 30 | "handle": [ 31 | { 32 | "body": "{http.regexp.1}", 33 | "handler": "static_response" 34 | } 35 | ], 36 | "match": [ 37 | { 38 | "path_regexp": { 39 | "name": "match", 40 | "pattern": "^/foo(.*)$" 41 | } 42 | } 43 | ] 44 | }, 45 | { 46 | "handle": [ 47 | { 48 | "body": "{http.request.header.content-type} {http.request.host.labels.0} {http.request.uri.query.p} {http.request.uri.path.0} {http.regexp.name.0}", 49 | "handler": "static_response" 50 | } 51 | ] 52 | } 53 | ] 54 | } 55 | ], 56 | "terminal": true 57 | } 58 | ] 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/sort_directives_with_any_matcher_first.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | respond 200 4 | 5 | @untrusted not remote_ip 10.1.1.0/24 6 | respond @untrusted 401 7 | ---------- 8 | { 9 | "apps": { 10 | "http": { 11 | "servers": { 12 | "srv0": { 13 | "listen": [ 14 | ":80" 15 | ], 16 | "routes": [ 17 | { 18 | "match": [ 19 | { 20 | "not": [ 21 | { 22 | "remote_ip": { 23 | "ranges": [ 24 | "10.1.1.0/24" 25 | ] 26 | } 27 | } 28 | ] 29 | } 30 | ], 31 | "handle": [ 32 | { 33 | "handler": "static_response", 34 | "status_code": 401 35 | } 36 | ] 37 | }, 38 | { 39 | "handle": [ 40 | { 41 | "handler": "static_response", 42 | "status_code": 200 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/sort_vars_in_reverse.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 2 | 3 | vars /foobar foo last 4 | vars /foo foo middle-last 5 | vars /foo* foo middle-first 6 | vars * foo first 7 | ---------- 8 | { 9 | "apps": { 10 | "http": { 11 | "servers": { 12 | "srv0": { 13 | "listen": [ 14 | ":80" 15 | ], 16 | "routes": [ 17 | { 18 | "handle": [ 19 | { 20 | "foo": "first", 21 | "handler": "vars" 22 | } 23 | ] 24 | }, 25 | { 26 | "match": [ 27 | { 28 | "path": [ 29 | "/foo*" 30 | ] 31 | } 32 | ], 33 | "handle": [ 34 | { 35 | "foo": "middle-first", 36 | "handler": "vars" 37 | } 38 | ] 39 | }, 40 | { 41 | "match": [ 42 | { 43 | "path": [ 44 | "/foo" 45 | ] 46 | } 47 | ], 48 | "handle": [ 49 | { 50 | "foo": "middle-last", 51 | "handler": "vars" 52 | } 53 | ] 54 | }, 55 | { 56 | "match": [ 57 | { 58 | "path": [ 59 | "/foobar" 60 | ] 61 | } 62 | ], 63 | "handle": [ 64 | { 65 | "foo": "last", 66 | "handler": "vars" 67 | } 68 | ] 69 | } 70 | ] 71 | } 72 | } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_acme_preferred_chains.caddyfiletest: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | tls { 4 | issuer acme { 5 | preferred_chains { 6 | any_common_name "Generic CA 1" "Generic CA 2" 7 | } 8 | } 9 | } 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":443" 18 | ], 19 | "routes": [ 20 | { 21 | "match": [ 22 | { 23 | "host": [ 24 | "localhost" 25 | ] 26 | } 27 | ], 28 | "terminal": true 29 | } 30 | ] 31 | } 32 | } 33 | }, 34 | "tls": { 35 | "automation": { 36 | "policies": [ 37 | { 38 | "subjects": [ 39 | "localhost" 40 | ], 41 | "issuers": [ 42 | { 43 | "module": "acme", 44 | "preferred_chains": { 45 | "any_common_name": [ 46 | "Generic CA 1", 47 | "Generic CA 2" 48 | ] 49 | } 50 | } 51 | ] 52 | } 53 | ] 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_automation_policies_1.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | local_certs 3 | } 4 | 5 | *.tld, *.*.tld { 6 | tls { 7 | on_demand 8 | } 9 | } 10 | 11 | foo.tld, www.foo.tld { 12 | } 13 | ---------- 14 | { 15 | "apps": { 16 | "http": { 17 | "servers": { 18 | "srv0": { 19 | "listen": [ 20 | ":443" 21 | ], 22 | "routes": [ 23 | { 24 | "match": [ 25 | { 26 | "host": [ 27 | "foo.tld", 28 | "www.foo.tld" 29 | ] 30 | } 31 | ], 32 | "terminal": true 33 | }, 34 | { 35 | "match": [ 36 | { 37 | "host": [ 38 | "*.tld", 39 | "*.*.tld" 40 | ] 41 | } 42 | ], 43 | "terminal": true 44 | } 45 | ] 46 | } 47 | } 48 | }, 49 | "tls": { 50 | "automation": { 51 | "policies": [ 52 | { 53 | "subjects": [ 54 | "foo.tld", 55 | "www.foo.tld" 56 | ], 57 | "issuers": [ 58 | { 59 | "module": "internal" 60 | } 61 | ] 62 | }, 63 | { 64 | "subjects": [ 65 | "*.*.tld", 66 | "*.tld" 67 | ], 68 | "issuers": [ 69 | { 70 | "module": "internal" 71 | } 72 | ], 73 | "on_demand": true 74 | }, 75 | { 76 | "issuers": [ 77 | { 78 | "module": "internal" 79 | } 80 | ] 81 | } 82 | ] 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_automation_policies_10.caddyfiletest: -------------------------------------------------------------------------------- 1 | # example from issue #4667 2 | { 3 | auto_https off 4 | } 5 | 6 | https://, example.com { 7 | tls test.crt test.key 8 | respond "Hello World" 9 | } 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":443" 18 | ], 19 | "routes": [ 20 | { 21 | "handle": [ 22 | { 23 | "body": "Hello World", 24 | "handler": "static_response" 25 | } 26 | ] 27 | } 28 | ], 29 | "tls_connection_policies": [ 30 | { 31 | "certificate_selection": { 32 | "any_tag": [ 33 | "cert0" 34 | ] 35 | } 36 | } 37 | ], 38 | "automatic_https": { 39 | "disable": true 40 | } 41 | } 42 | } 43 | }, 44 | "tls": { 45 | "certificates": { 46 | "load_files": [ 47 | { 48 | "certificate": "test.crt", 49 | "key": "test.key", 50 | "tags": [ 51 | "cert0" 52 | ] 53 | } 54 | ] 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_automation_policies_11.caddyfiletest: -------------------------------------------------------------------------------- 1 | # example from https://caddy.community/t/21415 2 | a.com { 3 | tls { 4 | get_certificate http http://foo.com/get 5 | } 6 | } 7 | 8 | b.com { 9 | } 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":443" 18 | ], 19 | "routes": [ 20 | { 21 | "match": [ 22 | { 23 | "host": [ 24 | "a.com" 25 | ] 26 | } 27 | ], 28 | "terminal": true 29 | }, 30 | { 31 | "match": [ 32 | { 33 | "host": [ 34 | "b.com" 35 | ] 36 | } 37 | ], 38 | "terminal": true 39 | } 40 | ] 41 | } 42 | } 43 | }, 44 | "tls": { 45 | "automation": { 46 | "policies": [ 47 | { 48 | "subjects": [ 49 | "a.com" 50 | ], 51 | "get_certificate": [ 52 | { 53 | "url": "http://foo.com/get", 54 | "via": "http" 55 | } 56 | ] 57 | }, 58 | { 59 | "subjects": [ 60 | "b.com" 61 | ] 62 | } 63 | ] 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_automation_policies_2.caddyfiletest: -------------------------------------------------------------------------------- 1 | # issue #3953 2 | { 3 | cert_issuer zerossl api_key 4 | } 5 | 6 | example.com { 7 | tls { 8 | on_demand 9 | key_type rsa2048 10 | } 11 | } 12 | 13 | http://example.net { 14 | } 15 | 16 | :1234 { 17 | } 18 | ---------- 19 | { 20 | "apps": { 21 | "http": { 22 | "servers": { 23 | "srv0": { 24 | "listen": [ 25 | ":1234" 26 | ] 27 | }, 28 | "srv1": { 29 | "listen": [ 30 | ":443" 31 | ], 32 | "routes": [ 33 | { 34 | "match": [ 35 | { 36 | "host": [ 37 | "example.com" 38 | ] 39 | } 40 | ], 41 | "terminal": true 42 | } 43 | ] 44 | }, 45 | "srv2": { 46 | "listen": [ 47 | ":80" 48 | ], 49 | "routes": [ 50 | { 51 | "match": [ 52 | { 53 | "host": [ 54 | "example.net" 55 | ] 56 | } 57 | ], 58 | "terminal": true 59 | } 60 | ] 61 | } 62 | } 63 | }, 64 | "tls": { 65 | "automation": { 66 | "policies": [ 67 | { 68 | "subjects": [ 69 | "example.com" 70 | ], 71 | "issuers": [ 72 | { 73 | "api_key": "api_key", 74 | "module": "zerossl" 75 | } 76 | ], 77 | "key_type": "rsa2048", 78 | "on_demand": true 79 | }, 80 | { 81 | "issuers": [ 82 | { 83 | "api_key": "api_key", 84 | "module": "zerossl" 85 | } 86 | ] 87 | } 88 | ] 89 | } 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_automation_policies_3.caddyfiletest: -------------------------------------------------------------------------------- 1 | # https://caddy.community/t/caddyfile-having-individual-sites-differ-from-global-options/11297 2 | { 3 | local_certs 4 | } 5 | 6 | a.example.com { 7 | tls internal 8 | } 9 | 10 | b.example.com { 11 | tls abc@example.com 12 | } 13 | 14 | c.example.com { 15 | } 16 | ---------- 17 | { 18 | "apps": { 19 | "http": { 20 | "servers": { 21 | "srv0": { 22 | "listen": [ 23 | ":443" 24 | ], 25 | "routes": [ 26 | { 27 | "match": [ 28 | { 29 | "host": [ 30 | "a.example.com" 31 | ] 32 | } 33 | ], 34 | "terminal": true 35 | }, 36 | { 37 | "match": [ 38 | { 39 | "host": [ 40 | "b.example.com" 41 | ] 42 | } 43 | ], 44 | "terminal": true 45 | }, 46 | { 47 | "match": [ 48 | { 49 | "host": [ 50 | "c.example.com" 51 | ] 52 | } 53 | ], 54 | "terminal": true 55 | } 56 | ] 57 | } 58 | } 59 | }, 60 | "tls": { 61 | "automation": { 62 | "policies": [ 63 | { 64 | "subjects": [ 65 | "b.example.com" 66 | ], 67 | "issuers": [ 68 | { 69 | "email": "abc@example.com", 70 | "module": "acme" 71 | }, 72 | { 73 | "ca": "https://acme.zerossl.com/v2/DV90", 74 | "email": "abc@example.com", 75 | "module": "acme" 76 | } 77 | ] 78 | }, 79 | { 80 | "issuers": [ 81 | { 82 | "module": "internal" 83 | } 84 | ] 85 | } 86 | ] 87 | } 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_automation_policies_5.caddyfiletest: -------------------------------------------------------------------------------- 1 | a.example.com { 2 | } 3 | 4 | b.example.com { 5 | } 6 | 7 | :443 { 8 | tls { 9 | on_demand 10 | } 11 | } 12 | ---------- 13 | { 14 | "apps": { 15 | "http": { 16 | "servers": { 17 | "srv0": { 18 | "listen": [ 19 | ":443" 20 | ], 21 | "routes": [ 22 | { 23 | "match": [ 24 | { 25 | "host": [ 26 | "a.example.com" 27 | ] 28 | } 29 | ], 30 | "terminal": true 31 | }, 32 | { 33 | "match": [ 34 | { 35 | "host": [ 36 | "b.example.com" 37 | ] 38 | } 39 | ], 40 | "terminal": true 41 | } 42 | ] 43 | } 44 | } 45 | }, 46 | "tls": { 47 | "automation": { 48 | "policies": [ 49 | { 50 | "subjects": [ 51 | "a.example.com", 52 | "b.example.com" 53 | ] 54 | }, 55 | { 56 | "on_demand": true 57 | } 58 | ] 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_automation_policies_7.caddyfiletest: -------------------------------------------------------------------------------- 1 | # (this Caddyfile is contrived, but based on issues #4176 and #4198) 2 | 3 | http://example.com { 4 | } 5 | 6 | https://example.com { 7 | tls internal 8 | } 9 | 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":443" 18 | ], 19 | "routes": [ 20 | { 21 | "match": [ 22 | { 23 | "host": [ 24 | "example.com" 25 | ] 26 | } 27 | ], 28 | "terminal": true 29 | } 30 | ] 31 | }, 32 | "srv1": { 33 | "listen": [ 34 | ":80" 35 | ], 36 | "routes": [ 37 | { 38 | "match": [ 39 | { 40 | "host": [ 41 | "example.com" 42 | ] 43 | } 44 | ], 45 | "terminal": true 46 | } 47 | ] 48 | } 49 | } 50 | }, 51 | "tls": { 52 | "automation": { 53 | "policies": [ 54 | { 55 | "subjects": [ 56 | "example.com" 57 | ], 58 | "issuers": [ 59 | { 60 | "module": "internal" 61 | } 62 | ] 63 | } 64 | ] 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_automation_policies_8.caddyfiletest: -------------------------------------------------------------------------------- 1 | # (this Caddyfile is contrived, but based on issues #4176 and #4198) 2 | 3 | http://example.com { 4 | } 5 | 6 | https://example.com { 7 | tls abc@example.com 8 | } 9 | 10 | http://localhost:8081 { 11 | } 12 | 13 | ---------- 14 | { 15 | "apps": { 16 | "http": { 17 | "servers": { 18 | "srv0": { 19 | "listen": [ 20 | ":443" 21 | ], 22 | "routes": [ 23 | { 24 | "match": [ 25 | { 26 | "host": [ 27 | "example.com" 28 | ] 29 | } 30 | ], 31 | "terminal": true 32 | } 33 | ] 34 | }, 35 | "srv1": { 36 | "listen": [ 37 | ":80" 38 | ], 39 | "routes": [ 40 | { 41 | "match": [ 42 | { 43 | "host": [ 44 | "example.com" 45 | ] 46 | } 47 | ], 48 | "terminal": true 49 | } 50 | ] 51 | }, 52 | "srv2": { 53 | "listen": [ 54 | ":8081" 55 | ], 56 | "routes": [ 57 | { 58 | "match": [ 59 | { 60 | "host": [ 61 | "localhost" 62 | ] 63 | } 64 | ], 65 | "terminal": true 66 | } 67 | ], 68 | "automatic_https": { 69 | "skip": [ 70 | "localhost" 71 | ] 72 | } 73 | } 74 | } 75 | }, 76 | "tls": { 77 | "automation": { 78 | "policies": [ 79 | { 80 | "subjects": [ 81 | "example.com" 82 | ], 83 | "issuers": [ 84 | { 85 | "email": "abc@example.com", 86 | "module": "acme" 87 | }, 88 | { 89 | "ca": "https://acme.zerossl.com/v2/DV90", 90 | "email": "abc@example.com", 91 | "module": "acme" 92 | } 93 | ] 94 | } 95 | ] 96 | } 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_automation_policies_9.caddyfiletest: -------------------------------------------------------------------------------- 1 | # example from issue #4640 2 | http://foo:8447, http://127.0.0.1:8447 { 3 | reverse_proxy 127.0.0.1:8080 4 | } 5 | ---------- 6 | { 7 | "apps": { 8 | "http": { 9 | "servers": { 10 | "srv0": { 11 | "listen": [ 12 | ":8447" 13 | ], 14 | "routes": [ 15 | { 16 | "match": [ 17 | { 18 | "host": [ 19 | "foo", 20 | "127.0.0.1" 21 | ] 22 | } 23 | ], 24 | "handle": [ 25 | { 26 | "handler": "subroute", 27 | "routes": [ 28 | { 29 | "handle": [ 30 | { 31 | "handler": "reverse_proxy", 32 | "upstreams": [ 33 | { 34 | "dial": "127.0.0.1:8080" 35 | } 36 | ] 37 | } 38 | ] 39 | } 40 | ] 41 | } 42 | ], 43 | "terminal": true 44 | } 45 | ], 46 | "automatic_https": { 47 | "skip": [ 48 | "foo", 49 | "127.0.0.1" 50 | ] 51 | } 52 | } 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_automation_policies_global_email_localhost.caddyfiletest: -------------------------------------------------------------------------------- 1 | { 2 | email foo@bar 3 | } 4 | 5 | localhost { 6 | } 7 | 8 | example.com { 9 | } 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":443" 18 | ], 19 | "routes": [ 20 | { 21 | "match": [ 22 | { 23 | "host": [ 24 | "example.com" 25 | ] 26 | } 27 | ], 28 | "terminal": true 29 | }, 30 | { 31 | "match": [ 32 | { 33 | "host": [ 34 | "localhost" 35 | ] 36 | } 37 | ], 38 | "terminal": true 39 | } 40 | ] 41 | } 42 | } 43 | }, 44 | "tls": { 45 | "automation": { 46 | "policies": [ 47 | { 48 | "subjects": [ 49 | "example.com" 50 | ], 51 | "issuers": [ 52 | { 53 | "email": "foo@bar", 54 | "module": "acme" 55 | }, 56 | { 57 | "ca": "https://acme.zerossl.com/v2/DV90", 58 | "email": "foo@bar", 59 | "module": "acme" 60 | } 61 | ] 62 | } 63 | ] 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_client_auth_cert_file.caddyfiletest: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | respond "hello from localhost" 4 | tls { 5 | client_auth { 6 | mode request 7 | trust_pool file { 8 | pem_file ../caddy.ca.cer 9 | } 10 | } 11 | } 12 | ---------- 13 | { 14 | "apps": { 15 | "http": { 16 | "servers": { 17 | "srv0": { 18 | "listen": [ 19 | ":443" 20 | ], 21 | "routes": [ 22 | { 23 | "match": [ 24 | { 25 | "host": [ 26 | "localhost" 27 | ] 28 | } 29 | ], 30 | "handle": [ 31 | { 32 | "handler": "subroute", 33 | "routes": [ 34 | { 35 | "handle": [ 36 | { 37 | "body": "hello from localhost", 38 | "handler": "static_response" 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | ], 45 | "terminal": true 46 | } 47 | ], 48 | "tls_connection_policies": [ 49 | { 50 | "match": { 51 | "sni": [ 52 | "localhost" 53 | ] 54 | }, 55 | "client_authentication": { 56 | "ca": { 57 | "pem_files": [ 58 | "../caddy.ca.cer" 59 | ], 60 | "provider": "file" 61 | }, 62 | "mode": "request" 63 | } 64 | }, 65 | {} 66 | ] 67 | } 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_dns_ttl.caddyfiletest: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | respond "hello from localhost" 4 | tls { 5 | dns_ttl 5m10s 6 | } 7 | ---------- 8 | { 9 | "apps": { 10 | "http": { 11 | "servers": { 12 | "srv0": { 13 | "listen": [ 14 | ":443" 15 | ], 16 | "routes": [ 17 | { 18 | "match": [ 19 | { 20 | "host": [ 21 | "localhost" 22 | ] 23 | } 24 | ], 25 | "handle": [ 26 | { 27 | "handler": "subroute", 28 | "routes": [ 29 | { 30 | "handle": [ 31 | { 32 | "body": "hello from localhost", 33 | "handler": "static_response" 34 | } 35 | ] 36 | } 37 | ] 38 | } 39 | ], 40 | "terminal": true 41 | } 42 | ] 43 | } 44 | } 45 | }, 46 | "tls": { 47 | "automation": { 48 | "policies": [ 49 | { 50 | "subjects": [ 51 | "localhost" 52 | ], 53 | "issuers": [ 54 | { 55 | "challenges": { 56 | "dns": { 57 | "ttl": 310000000000 58 | } 59 | }, 60 | "module": "acme" 61 | } 62 | ] 63 | } 64 | ] 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_explicit_issuer_dns_ttl.caddyfiletest: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | respond "hello from localhost" 4 | tls { 5 | issuer acme { 6 | dns_ttl 5m10s 7 | } 8 | issuer zerossl api_key { 9 | dns_ttl 10m20s 10 | } 11 | } 12 | ---------- 13 | { 14 | "apps": { 15 | "http": { 16 | "servers": { 17 | "srv0": { 18 | "listen": [ 19 | ":443" 20 | ], 21 | "routes": [ 22 | { 23 | "match": [ 24 | { 25 | "host": [ 26 | "localhost" 27 | ] 28 | } 29 | ], 30 | "handle": [ 31 | { 32 | "handler": "subroute", 33 | "routes": [ 34 | { 35 | "handle": [ 36 | { 37 | "body": "hello from localhost", 38 | "handler": "static_response" 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | ], 45 | "terminal": true 46 | } 47 | ] 48 | } 49 | } 50 | }, 51 | "tls": { 52 | "automation": { 53 | "policies": [ 54 | { 55 | "subjects": [ 56 | "localhost" 57 | ], 58 | "issuers": [ 59 | { 60 | "challenges": { 61 | "dns": { 62 | "ttl": 310000000000 63 | } 64 | }, 65 | "module": "acme" 66 | }, 67 | { 68 | "api_key": "api_key", 69 | "cname_validation": { 70 | "ttl": 620000000000 71 | }, 72 | "module": "zerossl" 73 | } 74 | ] 75 | } 76 | ] 77 | } 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_explicit_issuer_propagation_options.caddyfiletest: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | respond "hello from localhost" 4 | tls { 5 | issuer acme { 6 | propagation_delay 5m10s 7 | propagation_timeout 10m20s 8 | } 9 | issuer zerossl api_key { 10 | propagation_delay 5m30s 11 | propagation_timeout -1 12 | } 13 | } 14 | ---------- 15 | { 16 | "apps": { 17 | "http": { 18 | "servers": { 19 | "srv0": { 20 | "listen": [ 21 | ":443" 22 | ], 23 | "routes": [ 24 | { 25 | "match": [ 26 | { 27 | "host": [ 28 | "localhost" 29 | ] 30 | } 31 | ], 32 | "handle": [ 33 | { 34 | "handler": "subroute", 35 | "routes": [ 36 | { 37 | "handle": [ 38 | { 39 | "body": "hello from localhost", 40 | "handler": "static_response" 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | ], 47 | "terminal": true 48 | } 49 | ] 50 | } 51 | } 52 | }, 53 | "tls": { 54 | "automation": { 55 | "policies": [ 56 | { 57 | "subjects": [ 58 | "localhost" 59 | ], 60 | "issuers": [ 61 | { 62 | "challenges": { 63 | "dns": { 64 | "propagation_delay": 310000000000, 65 | "propagation_timeout": 620000000000 66 | } 67 | }, 68 | "module": "acme" 69 | }, 70 | { 71 | "api_key": "api_key", 72 | "cname_validation": { 73 | "propagation_delay": 330000000000, 74 | "propagation_timeout": -1 75 | }, 76 | "module": "zerossl" 77 | } 78 | ] 79 | } 80 | ] 81 | } 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_internal_options.caddyfiletest: -------------------------------------------------------------------------------- 1 | a.example.com { 2 | tls { 3 | issuer internal { 4 | ca foo 5 | lifetime 24h 6 | sign_with_root 7 | } 8 | } 9 | } 10 | ---------- 11 | { 12 | "apps": { 13 | "http": { 14 | "servers": { 15 | "srv0": { 16 | "listen": [ 17 | ":443" 18 | ], 19 | "routes": [ 20 | { 21 | "match": [ 22 | { 23 | "host": [ 24 | "a.example.com" 25 | ] 26 | } 27 | ], 28 | "terminal": true 29 | } 30 | ] 31 | } 32 | } 33 | }, 34 | "tls": { 35 | "automation": { 36 | "policies": [ 37 | { 38 | "subjects": [ 39 | "a.example.com" 40 | ], 41 | "issuers": [ 42 | { 43 | "ca": "foo", 44 | "lifetime": 86400000000000, 45 | "module": "internal", 46 | "sign_with_root": true 47 | } 48 | ] 49 | } 50 | ] 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tls_propagation_options.caddyfiletest: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | respond "hello from localhost" 4 | tls { 5 | propagation_delay 5m10s 6 | propagation_timeout 10m20s 7 | } 8 | ---------- 9 | { 10 | "apps": { 11 | "http": { 12 | "servers": { 13 | "srv0": { 14 | "listen": [ 15 | ":443" 16 | ], 17 | "routes": [ 18 | { 19 | "match": [ 20 | { 21 | "host": [ 22 | "localhost" 23 | ] 24 | } 25 | ], 26 | "handle": [ 27 | { 28 | "handler": "subroute", 29 | "routes": [ 30 | { 31 | "handle": [ 32 | { 33 | "body": "hello from localhost", 34 | "handler": "static_response" 35 | } 36 | ] 37 | } 38 | ] 39 | } 40 | ], 41 | "terminal": true 42 | } 43 | ] 44 | } 45 | } 46 | }, 47 | "tls": { 48 | "automation": { 49 | "policies": [ 50 | { 51 | "subjects": [ 52 | "localhost" 53 | ], 54 | "issuers": [ 55 | { 56 | "challenges": { 57 | "dns": { 58 | "propagation_delay": 310000000000, 59 | "propagation_timeout": 620000000000 60 | } 61 | }, 62 | "module": "acme" 63 | } 64 | ] 65 | } 66 | ] 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/tracing.caddyfiletest: -------------------------------------------------------------------------------- 1 | :80 { 2 | tracing /myhandler { 3 | span my-span 4 | } 5 | } 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":80" 14 | ], 15 | "routes": [ 16 | { 17 | "match": [ 18 | { 19 | "path": [ 20 | "/myhandler" 21 | ] 22 | } 23 | ], 24 | "handle": [ 25 | { 26 | "handler": "tracing", 27 | "span": "my-span" 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt/uri_replace_brace_escape.caddyfiletest: -------------------------------------------------------------------------------- 1 | :9080 2 | uri replace "\}" %7D 3 | uri replace "\{" %7B 4 | 5 | respond "{query}" 6 | ---------- 7 | { 8 | "apps": { 9 | "http": { 10 | "servers": { 11 | "srv0": { 12 | "listen": [ 13 | ":9080" 14 | ], 15 | "routes": [ 16 | { 17 | "handle": [ 18 | { 19 | "handler": "rewrite", 20 | "uri_substring": [ 21 | { 22 | "find": "\\}", 23 | "replace": "%7D" 24 | } 25 | ] 26 | }, 27 | { 28 | "handler": "rewrite", 29 | "uri_substring": [ 30 | { 31 | "find": "\\{", 32 | "replace": "%7B" 33 | } 34 | ] 35 | }, 36 | { 37 | "body": "{http.request.uri.query}", 38 | "handler": "static_response" 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /caddytest/integration/caddyfile_adapt_test.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | jsonMod "encoding/json" 5 | "fmt" 6 | "os" 7 | "path/filepath" 8 | "regexp" 9 | "strings" 10 | "testing" 11 | 12 | "github.com/caddyserver/caddy/v2/caddytest" 13 | 14 | _ "github.com/caddyserver/caddy/v2/internal/testmocks" 15 | ) 16 | 17 | func TestCaddyfileAdaptToJSON(t *testing.T) { 18 | // load the list of test files from the dir 19 | files, err := os.ReadDir("./caddyfile_adapt") 20 | if err != nil { 21 | t.Errorf("failed to read caddyfile_adapt dir: %s", err) 22 | } 23 | 24 | // prep a regexp to fix strings on windows 25 | winNewlines := regexp.MustCompile(`\r?\n`) 26 | 27 | for _, f := range files { 28 | if f.IsDir() { 29 | continue 30 | } 31 | 32 | // read the test file 33 | filename := f.Name() 34 | data, err := os.ReadFile("./caddyfile_adapt/" + filename) 35 | if err != nil { 36 | t.Errorf("failed to read %s dir: %s", filename, err) 37 | } 38 | 39 | // split the Caddyfile (first) and JSON (second) parts 40 | // (append newline to Caddyfile to match formatter expectations) 41 | parts := strings.Split(string(data), "----------") 42 | caddyfile, json := strings.TrimSpace(parts[0])+"\n", strings.TrimSpace(parts[1]) 43 | 44 | // replace windows newlines in the json with unix newlines 45 | json = winNewlines.ReplaceAllString(json, "\n") 46 | 47 | // replace os-specific default path for file_server's hide field 48 | replacePath, _ := jsonMod.Marshal(fmt.Sprint(".", string(filepath.Separator), "Caddyfile")) 49 | json = strings.ReplaceAll(json, `"./Caddyfile"`, string(replacePath)) 50 | 51 | // run the test 52 | ok := caddytest.CompareAdapt(t, filename, caddyfile, "caddyfile", json) 53 | if !ok { 54 | t.Errorf("failed to adapt %s", filename) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /caddytest/integration/handler_test.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | "bytes" 5 | "net/http" 6 | "testing" 7 | 8 | "github.com/caddyserver/caddy/v2/caddytest" 9 | ) 10 | 11 | func TestBrowse(t *testing.T) { 12 | tester := caddytest.NewTester(t) 13 | tester.InitServer(` 14 | { 15 | skip_install_trust 16 | admin localhost:2999 17 | http_port 9080 18 | https_port 9443 19 | grace_period 1ns 20 | } 21 | http://localhost:9080 { 22 | file_server browse 23 | } 24 | `, "caddyfile") 25 | 26 | req, err := http.NewRequest(http.MethodGet, "http://localhost:9080/", nil) 27 | if err != nil { 28 | t.Fail() 29 | return 30 | } 31 | tester.AssertResponseCode(req, 200) 32 | } 33 | 34 | func TestRespondWithJSON(t *testing.T) { 35 | tester := caddytest.NewTester(t) 36 | tester.InitServer(` 37 | { 38 | skip_install_trust 39 | admin localhost:2999 40 | http_port 9080 41 | https_port 9443 42 | grace_period 1ns 43 | } 44 | localhost { 45 | respond {http.request.body} 46 | } 47 | `, "caddyfile") 48 | 49 | res, _ := tester.AssertPostResponseBody("https://localhost:9443/", 50 | nil, 51 | bytes.NewBufferString(`{ 52 | "greeting": "Hello, world!" 53 | }`), 200, `{ 54 | "greeting": "Hello, world!" 55 | }`) 56 | if res.Header.Get("Content-Type") != "application/json" { 57 | t.Errorf("expected Content-Type to be application/json, but was %s", res.Header.Get("Content-Type")) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /caddytest/integration/intercept_test.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/caddyserver/caddy/v2/caddytest" 7 | ) 8 | 9 | func TestIntercept(t *testing.T) { 10 | tester := caddytest.NewTester(t) 11 | tester.InitServer(`{ 12 | skip_install_trust 13 | admin localhost:2999 14 | http_port 9080 15 | https_port 9443 16 | grace_period 1ns 17 | } 18 | 19 | localhost:9080 { 20 | respond /intercept "I'm a teapot" 408 21 | header /intercept To-Intercept ok 22 | respond /no-intercept "I'm not a teapot" 23 | 24 | intercept { 25 | @teapot status 408 26 | handle_response @teapot { 27 | header /intercept intercepted {resp.header.To-Intercept} 28 | respond /intercept "I'm a combined coffee/tea pot that is temporarily out of coffee" 503 29 | } 30 | } 31 | } 32 | `, "caddyfile") 33 | 34 | r, _ := tester.AssertGetResponse("http://localhost:9080/intercept", 503, "I'm a combined coffee/tea pot that is temporarily out of coffee") 35 | if r.Header.Get("intercepted") != "ok" { 36 | t.Fatalf(`header "intercepted" value is not "ok": %s`, r.Header.Get("intercepted")) 37 | } 38 | 39 | tester.AssertGetResponse("http://localhost:9080/no-intercept", 200, "I'm not a teapot") 40 | } 41 | -------------------------------------------------------------------------------- /caddytest/integration/leafcertloaders_test.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/caddyserver/caddy/v2/caddytest" 7 | ) 8 | 9 | func TestLeafCertLoaders(t *testing.T) { 10 | tester := caddytest.NewTester(t) 11 | tester.InitServer(` 12 | { 13 | "admin": { 14 | "listen": "localhost:2999" 15 | }, 16 | "apps": { 17 | "http": { 18 | "http_port": 9080, 19 | "https_port": 9443, 20 | "grace_period": 1, 21 | "servers": { 22 | "srv0": { 23 | "listen": [ 24 | ":9443" 25 | ], 26 | "routes": [ 27 | { 28 | "match": [ 29 | { 30 | "host": [ 31 | "localhost" 32 | ] 33 | } 34 | ], 35 | "terminal": true 36 | } 37 | ], 38 | "tls_connection_policies": [ 39 | { 40 | "client_authentication": { 41 | "verifiers": [ 42 | { 43 | "verifier": "leaf", 44 | "leaf_certs_loaders": [ 45 | { 46 | "loader": "file", 47 | "files": ["../leafcert.pem"] 48 | }, 49 | { 50 | "loader": "folder", 51 | "folders": ["../"] 52 | }, 53 | { 54 | "loader": "storage" 55 | }, 56 | { 57 | "loader": "pem" 58 | } 59 | ] 60 | } 61 | ] 62 | } 63 | } 64 | ] 65 | } 66 | } 67 | } 68 | } 69 | }`, "json") 70 | } 71 | -------------------------------------------------------------------------------- /caddytest/integration/testdata/cookie.html: -------------------------------------------------------------------------------- 1 |

Cookie.ClientName {{.Cookie "clientname"}}

-------------------------------------------------------------------------------- /caddytest/integration/testdata/foo.txt: -------------------------------------------------------------------------------- 1 | foo -------------------------------------------------------------------------------- /caddytest/integration/testdata/foo_with_multiple_trailing_newlines.txt: -------------------------------------------------------------------------------- 1 | foo 2 | 3 | -------------------------------------------------------------------------------- /caddytest/integration/testdata/foo_with_trailing_newline.txt: -------------------------------------------------------------------------------- 1 | foo 2 | -------------------------------------------------------------------------------- /caddytest/integration/testdata/import_respond.txt: -------------------------------------------------------------------------------- 1 | respond "'I am {args[0]}', hears {args[1]}" -------------------------------------------------------------------------------- /caddytest/integration/testdata/index.localhost.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caddyserver/caddy/5b2eb664188775973cb8254d4e21544572866a47/caddytest/integration/testdata/index.localhost.html -------------------------------------------------------------------------------- /caddytest/leafcert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL 3 | MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC 4 | VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx 5 | NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD 6 | TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu 7 | ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j 8 | V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj 9 | gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA 10 | FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE 11 | CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS 12 | BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE 13 | BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju 14 | Wm7DCfrPNGVwFWUQOmsPue9rZBgO 15 | -----END CERTIFICATE----- 16 | -------------------------------------------------------------------------------- /cmd/caddy/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package main is the entry point of the Caddy application. 16 | // Most of Caddy's functionality is provided through modules, 17 | // which can be plugged in by adding their import below. 18 | // 19 | // There is no need to modify the Caddy source code to customize your 20 | // builds. You can easily build a custom Caddy with these simple steps: 21 | // 22 | // 1. Copy this file (main.go) into a new folder 23 | // 2. Edit the imports below to include the modules you want plugged in 24 | // 3. Run `go mod init caddy` 25 | // 4. Run `go install` or `go build` - you now have a custom binary! 26 | // 27 | // Or you can use xcaddy which does it all for you as a command: 28 | // https://github.com/caddyserver/xcaddy 29 | package main 30 | 31 | import ( 32 | caddycmd "github.com/caddyserver/caddy/v2/cmd" 33 | 34 | // plug in Caddy modules here 35 | _ "github.com/caddyserver/caddy/v2/modules/standard" 36 | ) 37 | 38 | func main() { 39 | caddycmd.Main() 40 | } 41 | -------------------------------------------------------------------------------- /cmd/caddy/setcap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # USAGE: 4 | # go run -exec ./setcap.sh main.go 5 | # 6 | # (Example: `go run -exec ./setcap.sh main.go run --config caddy.json`) 7 | # 8 | # For some reason this does not work on my Arch system, so if you find that's 9 | # the case, you can instead do: 10 | # 11 | # go build && ./setcap.sh ./caddy 12 | # 13 | # but this will leave the ./caddy binary laying around. 14 | # 15 | 16 | sudo setcap cap_net_bind_service=+ep "$1" 17 | "$@" 18 | -------------------------------------------------------------------------------- /cmd/commandfactory.go: -------------------------------------------------------------------------------- 1 | package caddycmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | type rootCommandFactory struct { 8 | constructor func() *cobra.Command 9 | options []func(*cobra.Command) 10 | } 11 | 12 | func newRootCommandFactory(fn func() *cobra.Command) *rootCommandFactory { 13 | return &rootCommandFactory{ 14 | constructor: fn, 15 | } 16 | } 17 | 18 | func (f *rootCommandFactory) Use(fn func(cmd *cobra.Command)) { 19 | f.options = append(f.options, fn) 20 | } 21 | 22 | func (f *rootCommandFactory) Build() *cobra.Command { 23 | o := f.constructor() 24 | for _, v := range f.options { 25 | v(o) 26 | } 27 | return o 28 | } 29 | -------------------------------------------------------------------------------- /cmd/removebinary.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build !windows 16 | 17 | package caddycmd 18 | 19 | import ( 20 | "os" 21 | ) 22 | 23 | // removeCaddyBinary removes the Caddy binary at the given path. 24 | // 25 | // On any non-Windows OS, this simply calls os.Remove, since they should 26 | // probably not exhibit any issue with processes deleting themselves. 27 | func removeCaddyBinary(path string) error { 28 | return os.Remove(path) 29 | } 30 | -------------------------------------------------------------------------------- /cmd/removebinary_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package caddycmd 16 | 17 | import ( 18 | "os" 19 | "path/filepath" 20 | "syscall" 21 | ) 22 | 23 | // removeCaddyBinary removes the Caddy binary at the given path. 24 | // 25 | // On Windows, this uses a syscall to indirectly remove the file, 26 | // because otherwise we get an "Access is denied." error when trying 27 | // to delete the binary while Caddy is still running and performing 28 | // the upgrade. "cmd.exe /C" executes a command specified by the 29 | // following arguments, i.e. "del" which will run as a separate process, 30 | // which avoids the "Access is denied." error. 31 | func removeCaddyBinary(path string) error { 32 | var sI syscall.StartupInfo 33 | var pI syscall.ProcessInformation 34 | argv, err := syscall.UTF16PtrFromString(filepath.Join(os.Getenv("windir"), "system32", "cmd.exe") + " /C del " + path) 35 | if err != nil { 36 | return err 37 | } 38 | return syscall.CreateProcess(nil, argv, nil, nil, true, 0, nil, nil, &sI, &pI) 39 | } 40 | -------------------------------------------------------------------------------- /cmd/x509rootsfallback.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package caddycmd 16 | 17 | import ( 18 | // For running in minimal environments, this can ease 19 | // headaches related to establishing TLS connections. 20 | // "Package fallback embeds a set of fallback X.509 trusted 21 | // roots in the application by automatically invoking 22 | // x509.SetFallbackRoots. This allows the application to 23 | // work correctly even if the operating system does not 24 | // provide a verifier or system roots pool. ... It's 25 | // recommended that only binaries, and not libraries, 26 | // import this package. This package must be kept up to 27 | // date for security and compatibility reasons." 28 | // 29 | // This is in its own file only because of conflicts 30 | // between gci and goimports when in main.go. 31 | // See https://github.com/daixiang0/gci/issues/76 32 | _ "golang.org/x/crypto/x509roots/fallback" 33 | ) 34 | -------------------------------------------------------------------------------- /duration_fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build gofuzz 16 | 17 | package caddy 18 | 19 | func FuzzParseDuration(data []byte) int { 20 | _, err := ParseDuration(string(data)) 21 | if err != nil { 22 | return 0 23 | } 24 | return 1 25 | } 26 | -------------------------------------------------------------------------------- /filepath.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build !windows 16 | 17 | package caddy 18 | 19 | import ( 20 | "os" 21 | "path/filepath" 22 | ) 23 | 24 | // FastAbs is an optimized version of filepath.Abs for Unix systems, 25 | // since we don't expect the working directory to ever change once 26 | // Caddy is running. Avoid the os.Getwd() syscall overhead. 27 | // It's overall the same as stdlib's implementation, the difference 28 | // being cached working directory. 29 | func FastAbs(path string) (string, error) { 30 | if filepath.IsAbs(path) { 31 | return filepath.Clean(path), nil 32 | } 33 | if wderr != nil { 34 | return "", wderr 35 | } 36 | return filepath.Join(wd, path), nil 37 | } 38 | 39 | var wd, wderr = os.Getwd() 40 | -------------------------------------------------------------------------------- /filepath_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package caddy 16 | 17 | import ( 18 | "path/filepath" 19 | ) 20 | 21 | // FastAbs can't be optimized on Windows because there 22 | // are special file paths that require the use of syscall.FullPath 23 | // to handle correctly. 24 | // Just call stdlib's implementation which uses that function. 25 | func FastAbs(path string) (string, error) { 26 | return filepath.Abs(path) 27 | } 28 | -------------------------------------------------------------------------------- /filesystem.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package caddy 16 | 17 | import "io/fs" 18 | 19 | type FileSystems interface { 20 | Register(k string, v fs.FS) 21 | Unregister(k string) 22 | Get(k string) (v fs.FS, ok bool) 23 | Default() fs.FS 24 | } 25 | -------------------------------------------------------------------------------- /internal/filesystems/os.go: -------------------------------------------------------------------------------- 1 | package filesystems 2 | 3 | import ( 4 | "io/fs" 5 | "os" 6 | "path/filepath" 7 | ) 8 | 9 | // OsFS is a simple fs.FS implementation that uses the local 10 | // file system. (We do not use os.DirFS because we do our own 11 | // rooting or path prefixing without being constrained to a single 12 | // root folder. The standard os.DirFS implementation is problematic 13 | // since roots can be dynamic in our application.) 14 | // 15 | // OsFS also implements fs.StatFS, fs.GlobFS, fs.ReadDirFS, and fs.ReadFileFS. 16 | type OsFS struct{} 17 | 18 | func (OsFS) Open(name string) (fs.File, error) { return os.Open(name) } 19 | func (OsFS) Stat(name string) (fs.FileInfo, error) { return os.Stat(name) } 20 | func (OsFS) Glob(pattern string) ([]string, error) { return filepath.Glob(pattern) } 21 | func (OsFS) ReadDir(name string) ([]fs.DirEntry, error) { return os.ReadDir(name) } 22 | func (OsFS) ReadFile(name string) ([]byte, error) { return os.ReadFile(name) } 23 | 24 | var ( 25 | _ fs.StatFS = (*OsFS)(nil) 26 | _ fs.GlobFS = (*OsFS)(nil) 27 | _ fs.ReadDirFS = (*OsFS)(nil) 28 | _ fs.ReadFileFS = (*OsFS)(nil) 29 | ) 30 | -------------------------------------------------------------------------------- /internal/logs.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | // MaxSizeSubjectsListForLog returns the keys in the map as a slice of maximum length 6 | // maxToDisplay. It is useful for logging domains being managed, for example, since a 7 | // map is typically needed for quick lookup, but a slice is needed for logging, and this 8 | // can be quite a doozy since there may be a huge amount (hundreds of thousands). 9 | func MaxSizeSubjectsListForLog(subjects map[string]struct{}, maxToDisplay int) []string { 10 | numberOfNamesToDisplay := min(len(subjects), maxToDisplay) 11 | domainsToDisplay := make([]string, 0, numberOfNamesToDisplay) 12 | for domain := range subjects { 13 | domainsToDisplay = append(domainsToDisplay, domain) 14 | if len(domainsToDisplay) >= numberOfNamesToDisplay { 15 | break 16 | } 17 | } 18 | if len(subjects) > maxToDisplay { 19 | domainsToDisplay = append(domainsToDisplay, fmt.Sprintf("(and %d more...)", len(subjects)-maxToDisplay)) 20 | } 21 | return domainsToDisplay 22 | } 23 | -------------------------------------------------------------------------------- /internal/metrics/metrics.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | ) 7 | 8 | func SanitizeCode(s int) string { 9 | switch s { 10 | case 0, 200: 11 | return "200" 12 | default: 13 | return strconv.Itoa(s) 14 | } 15 | } 16 | 17 | // Only support the list of "regular" HTTP methods, see 18 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods 19 | var methodMap = map[string]string{ 20 | "GET": http.MethodGet, "get": http.MethodGet, 21 | "HEAD": http.MethodHead, "head": http.MethodHead, 22 | "PUT": http.MethodPut, "put": http.MethodPut, 23 | "POST": http.MethodPost, "post": http.MethodPost, 24 | "DELETE": http.MethodDelete, "delete": http.MethodDelete, 25 | "CONNECT": http.MethodConnect, "connect": http.MethodConnect, 26 | "OPTIONS": http.MethodOptions, "options": http.MethodOptions, 27 | "TRACE": http.MethodTrace, "trace": http.MethodTrace, 28 | "PATCH": http.MethodPatch, "patch": http.MethodPatch, 29 | } 30 | 31 | // SanitizeMethod sanitizes the method for use as a metric label. This helps 32 | // prevent high cardinality on the method label. The name is always upper case. 33 | func SanitizeMethod(m string) string { 34 | if m, ok := methodMap[m]; ok { 35 | return m 36 | } 37 | 38 | return "OTHER" 39 | } 40 | -------------------------------------------------------------------------------- /internal/metrics/metrics_test.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "strings" 5 | "testing" 6 | ) 7 | 8 | func TestSanitizeMethod(t *testing.T) { 9 | tests := []struct { 10 | method string 11 | expected string 12 | }{ 13 | {method: "get", expected: "GET"}, 14 | {method: "POST", expected: "POST"}, 15 | {method: "OPTIONS", expected: "OPTIONS"}, 16 | {method: "connect", expected: "CONNECT"}, 17 | {method: "trace", expected: "TRACE"}, 18 | {method: "UNKNOWN", expected: "OTHER"}, 19 | {method: strings.Repeat("ohno", 9999), expected: "OTHER"}, 20 | } 21 | 22 | for _, d := range tests { 23 | actual := SanitizeMethod(d.method) 24 | if actual != d.expected { 25 | t.Errorf("Not same: expected %#v, but got %#v", d.expected, actual) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /internal/ranges.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | // PrivateRangesCIDR returns a list of private CIDR range 4 | // strings, which can be used as a configuration shortcut. 5 | func PrivateRangesCIDR() []string { 6 | return []string{ 7 | "192.168.0.0/16", 8 | "172.16.0.0/12", 9 | "10.0.0.0/8", 10 | "127.0.0.1/8", 11 | "fd00::/8", 12 | "::1", 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /internal/testmocks/dummyverifier.go: -------------------------------------------------------------------------------- 1 | package testmocks 2 | 3 | import ( 4 | "crypto/x509" 5 | 6 | "github.com/caddyserver/caddy/v2" 7 | "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" 8 | "github.com/caddyserver/caddy/v2/modules/caddytls" 9 | ) 10 | 11 | func init() { 12 | caddy.RegisterModule(new(dummyVerifier)) 13 | } 14 | 15 | type dummyVerifier struct{} 16 | 17 | // UnmarshalCaddyfile implements caddyfile.Unmarshaler. 18 | func (dummyVerifier) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { 19 | return nil 20 | } 21 | 22 | // CaddyModule implements caddy.Module. 23 | func (dummyVerifier) CaddyModule() caddy.ModuleInfo { 24 | return caddy.ModuleInfo{ 25 | ID: "tls.client_auth.verifier.dummy", 26 | New: func() caddy.Module { 27 | return new(dummyVerifier) 28 | }, 29 | } 30 | } 31 | 32 | // VerifyClientCertificate implements ClientCertificateVerifier. 33 | func (dummyVerifier) VerifyClientCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { 34 | return nil 35 | } 36 | 37 | var ( 38 | _ caddy.Module = dummyVerifier{} 39 | _ caddytls.ClientCertificateVerifier = dummyVerifier{} 40 | _ caddyfile.Unmarshaler = dummyVerifier{} 41 | ) 42 | -------------------------------------------------------------------------------- /listen_unix_setopt.go: -------------------------------------------------------------------------------- 1 | //go:build unix && !freebsd && !solaris 2 | 3 | package caddy 4 | 5 | import "golang.org/x/sys/unix" 6 | 7 | const unixSOREUSEPORT = unix.SO_REUSEPORT 8 | -------------------------------------------------------------------------------- /listen_unix_setopt_freebsd.go: -------------------------------------------------------------------------------- 1 | //go:build freebsd 2 | 3 | package caddy 4 | 5 | import "golang.org/x/sys/unix" 6 | 7 | const unixSOREUSEPORT = unix.SO_REUSEPORT_LB 8 | -------------------------------------------------------------------------------- /listeners_fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build gofuzz 16 | 17 | package caddy 18 | 19 | func FuzzParseNetworkAddress(data []byte) int { 20 | _, err := ParseNetworkAddress(string(data)) 21 | if err != nil { 22 | return 0 23 | } 24 | return 1 25 | } 26 | -------------------------------------------------------------------------------- /modules/caddyhttp/encode/brotli/brotli_precompressed.go: -------------------------------------------------------------------------------- 1 | package caddybrotli 2 | 3 | import ( 4 | "github.com/caddyserver/caddy/v2" 5 | "github.com/caddyserver/caddy/v2/modules/caddyhttp/encode" 6 | ) 7 | 8 | func init() { 9 | caddy.RegisterModule(BrotliPrecompressed{}) 10 | } 11 | 12 | // BrotliPrecompressed provides the file extension for files precompressed with brotli encoding. 13 | type BrotliPrecompressed struct{} 14 | 15 | // CaddyModule returns the Caddy module information. 16 | func (BrotliPrecompressed) CaddyModule() caddy.ModuleInfo { 17 | return caddy.ModuleInfo{ 18 | ID: "http.precompressed.br", 19 | New: func() caddy.Module { return new(BrotliPrecompressed) }, 20 | } 21 | } 22 | 23 | // AcceptEncoding returns the name of the encoding as 24 | // used in the Accept-Encoding request headers. 25 | func (BrotliPrecompressed) AcceptEncoding() string { return "br" } 26 | 27 | // Suffix returns the filename suffix of precompressed files. 28 | func (BrotliPrecompressed) Suffix() string { return ".br" } 29 | 30 | // Interface guards 31 | var _ encode.Precompressed = (*BrotliPrecompressed)(nil) 32 | -------------------------------------------------------------------------------- /modules/caddyhttp/encode/gzip/gzip_precompressed.go: -------------------------------------------------------------------------------- 1 | package caddygzip 2 | 3 | import ( 4 | "github.com/caddyserver/caddy/v2" 5 | "github.com/caddyserver/caddy/v2/modules/caddyhttp/encode" 6 | ) 7 | 8 | func init() { 9 | caddy.RegisterModule(GzipPrecompressed{}) 10 | } 11 | 12 | // GzipPrecompressed provides the file extension for files precompressed with gzip encoding. 13 | type GzipPrecompressed struct { 14 | Gzip 15 | } 16 | 17 | // CaddyModule returns the Caddy module information. 18 | func (GzipPrecompressed) CaddyModule() caddy.ModuleInfo { 19 | return caddy.ModuleInfo{ 20 | ID: "http.precompressed.gzip", 21 | New: func() caddy.Module { return new(GzipPrecompressed) }, 22 | } 23 | } 24 | 25 | // Suffix returns the filename suffix of precompressed files. 26 | func (GzipPrecompressed) Suffix() string { return ".gz" } 27 | 28 | var _ encode.Precompressed = (*GzipPrecompressed)(nil) 29 | -------------------------------------------------------------------------------- /modules/caddyhttp/encode/zstd/zstd_precompressed.go: -------------------------------------------------------------------------------- 1 | package caddyzstd 2 | 3 | import ( 4 | "github.com/caddyserver/caddy/v2" 5 | "github.com/caddyserver/caddy/v2/modules/caddyhttp/encode" 6 | ) 7 | 8 | func init() { 9 | caddy.RegisterModule(ZstdPrecompressed{}) 10 | } 11 | 12 | // ZstdPrecompressed provides the file extension for files precompressed with zstandard encoding. 13 | type ZstdPrecompressed struct { 14 | Zstd 15 | } 16 | 17 | // CaddyModule returns the Caddy module information. 18 | func (ZstdPrecompressed) CaddyModule() caddy.ModuleInfo { 19 | return caddy.ModuleInfo{ 20 | ID: "http.precompressed.zstd", 21 | New: func() caddy.Module { return new(ZstdPrecompressed) }, 22 | } 23 | } 24 | 25 | // Suffix returns the filename suffix of precompressed files. 26 | func (ZstdPrecompressed) Suffix() string { return ".zst" } 27 | 28 | var _ encode.Precompressed = (*ZstdPrecompressed)(nil) 29 | -------------------------------------------------------------------------------- /modules/caddyhttp/fileserver/testdata/%D9%85%D9%84%D9%81.txt: -------------------------------------------------------------------------------- 1 | %D9%85%D9%84%D9%81.txt -------------------------------------------------------------------------------- /modules/caddyhttp/fileserver/testdata/foo.php.php/index.php: -------------------------------------------------------------------------------- 1 | foo.php.php/index.php 2 | -------------------------------------------------------------------------------- /modules/caddyhttp/fileserver/testdata/foo.txt: -------------------------------------------------------------------------------- 1 | foo.txt -------------------------------------------------------------------------------- /modules/caddyhttp/fileserver/testdata/foodir/bar.txt: -------------------------------------------------------------------------------- 1 | foodir/bar.txt -------------------------------------------------------------------------------- /modules/caddyhttp/fileserver/testdata/foodir/foo.txt: -------------------------------------------------------------------------------- 1 | foodir/foo.txt -------------------------------------------------------------------------------- /modules/caddyhttp/fileserver/testdata/index.php: -------------------------------------------------------------------------------- 1 | index.php -------------------------------------------------------------------------------- /modules/caddyhttp/fileserver/testdata/large.txt: -------------------------------------------------------------------------------- 1 | This is a file with more content than the other files in this directory 2 | such that tests using the largest_size policy pick this file, or the 3 | smallest_size policy avoids this file. -------------------------------------------------------------------------------- /modules/caddyhttp/fileserver/testdata/notphp.php.txt: -------------------------------------------------------------------------------- 1 | notphp.php.txt 2 | -------------------------------------------------------------------------------- /modules/caddyhttp/fileserver/testdata/remote.php: -------------------------------------------------------------------------------- 1 | remote.php -------------------------------------------------------------------------------- /modules/caddyhttp/fileserver/testdata/ملف.txt: -------------------------------------------------------------------------------- 1 | ملف.txt -------------------------------------------------------------------------------- /modules/caddyhttp/invoke.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package caddyhttp 16 | 17 | import ( 18 | "fmt" 19 | "net/http" 20 | 21 | "github.com/caddyserver/caddy/v2" 22 | ) 23 | 24 | func init() { 25 | caddy.RegisterModule(Invoke{}) 26 | } 27 | 28 | // Invoke implements a handler that compiles and executes a 29 | // named route that was defined on the server. 30 | // 31 | // EXPERIMENTAL: Subject to change or removal. 32 | type Invoke struct { 33 | // Name is the key of the named route to execute 34 | Name string `json:"name,omitempty"` 35 | } 36 | 37 | // CaddyModule returns the Caddy module information. 38 | func (Invoke) CaddyModule() caddy.ModuleInfo { 39 | return caddy.ModuleInfo{ 40 | ID: "http.handlers.invoke", 41 | New: func() caddy.Module { return new(Invoke) }, 42 | } 43 | } 44 | 45 | func (invoke *Invoke) ServeHTTP(w http.ResponseWriter, r *http.Request, next Handler) error { 46 | server := r.Context().Value(ServerCtxKey).(*Server) 47 | if route, ok := server.NamedRoutes[invoke.Name]; ok { 48 | return route.Compile(next).ServeHTTP(w, r) 49 | } 50 | return fmt.Errorf("invoke: route '%s' not found", invoke.Name) 51 | } 52 | 53 | // Interface guards 54 | var ( 55 | _ MiddlewareHandler = (*Invoke)(nil) 56 | ) 57 | -------------------------------------------------------------------------------- /modules/caddyhttp/logging/caddyfile.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package logging 16 | 17 | import ( 18 | "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" 19 | "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile" 20 | "github.com/caddyserver/caddy/v2/modules/caddyhttp" 21 | ) 22 | 23 | func init() { 24 | httpcaddyfile.RegisterHandlerDirective("log_append", parseCaddyfile) 25 | } 26 | 27 | // parseCaddyfile sets up the log_append handler from Caddyfile tokens. Syntax: 28 | // 29 | // log_append [] 30 | func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) { 31 | handler := new(LogAppend) 32 | err := handler.UnmarshalCaddyfile(h.Dispenser) 33 | return handler, err 34 | } 35 | 36 | // UnmarshalCaddyfile implements caddyfile.Unmarshaler. 37 | func (h *LogAppend) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { 38 | d.Next() // consume directive name 39 | if !d.NextArg() { 40 | return d.ArgErr() 41 | } 42 | h.Key = d.Val() 43 | if !d.NextArg() { 44 | return d.ArgErr() 45 | } 46 | h.Value = d.Val() 47 | return nil 48 | } 49 | 50 | // Interface guards 51 | var ( 52 | _ caddyfile.Unmarshaler = (*LogAppend)(nil) 53 | ) 54 | -------------------------------------------------------------------------------- /modules/caddyhttp/reverseproxy/fastcgi/header.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package fastcgi 16 | 17 | type header struct { 18 | Version uint8 19 | Type uint8 20 | ID uint16 21 | ContentLength uint16 22 | PaddingLength uint8 23 | Reserved uint8 24 | } 25 | 26 | func (h *header) init(recType uint8, reqID uint16, contentLength int) { 27 | h.Version = 1 28 | h.Type = recType 29 | h.ID = reqID 30 | h.ContentLength = uint16(contentLength) 31 | h.PaddingLength = uint8(-contentLength & 7) 32 | } 33 | -------------------------------------------------------------------------------- /modules/caddyhttp/reverseproxy/fastcgi/pool.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package fastcgi 16 | 17 | import ( 18 | "bytes" 19 | "sync" 20 | ) 21 | 22 | var bufPool = sync.Pool{ 23 | New: func() any { 24 | return new(bytes.Buffer) 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /modules/caddyhttp/reverseproxy/fastcgi/reader.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package fastcgi 16 | 17 | import ( 18 | "bytes" 19 | "io" 20 | ) 21 | 22 | type streamReader struct { 23 | c *client 24 | rec record 25 | stderr bytes.Buffer 26 | } 27 | 28 | func (w *streamReader) Read(p []byte) (n int, err error) { 29 | for !w.rec.hasMore() { 30 | err = w.rec.fill(w.c.rwc) 31 | if err != nil { 32 | return 0, err 33 | } 34 | 35 | // standard error output 36 | if w.rec.h.Type == Stderr { 37 | if _, err = io.Copy(&w.stderr, &w.rec); err != nil { 38 | return 0, err 39 | } 40 | } 41 | } 42 | 43 | return w.rec.Read(p) 44 | } 45 | -------------------------------------------------------------------------------- /modules/caddyhttp/reverseproxy/fastcgi/record.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package fastcgi 16 | 17 | import ( 18 | "encoding/binary" 19 | "errors" 20 | "io" 21 | ) 22 | 23 | type record struct { 24 | h header 25 | lr io.LimitedReader 26 | padding int64 27 | } 28 | 29 | func (rec *record) fill(r io.Reader) (err error) { 30 | rec.lr.N = rec.padding 31 | rec.lr.R = r 32 | if _, err = io.Copy(io.Discard, rec); err != nil { 33 | return 34 | } 35 | 36 | if err = binary.Read(r, binary.BigEndian, &rec.h); err != nil { 37 | return 38 | } 39 | if rec.h.Version != 1 { 40 | err = errors.New("fcgi: invalid header version") 41 | return 42 | } 43 | if rec.h.Type == EndRequest { 44 | err = io.EOF 45 | return 46 | } 47 | rec.lr.N = int64(rec.h.ContentLength) 48 | rec.padding = int64(rec.h.PaddingLength) 49 | return 50 | } 51 | 52 | func (rec *record) Read(p []byte) (n int, err error) { 53 | return rec.lr.Read(p) 54 | } 55 | 56 | func (rec *record) hasMore() bool { 57 | return rec.lr.N > 0 58 | } 59 | -------------------------------------------------------------------------------- /modules/caddyhttp/reverseproxy/streaming_test.go: -------------------------------------------------------------------------------- 1 | package reverseproxy 2 | 3 | import ( 4 | "bytes" 5 | "net/http/httptest" 6 | "strings" 7 | "testing" 8 | 9 | "github.com/caddyserver/caddy/v2" 10 | ) 11 | 12 | func TestHandlerCopyResponse(t *testing.T) { 13 | h := Handler{} 14 | testdata := []string{ 15 | "", 16 | strings.Repeat("a", defaultBufferSize), 17 | strings.Repeat("123456789 123456789 123456789 12", 3000), 18 | } 19 | 20 | dst := bytes.NewBuffer(nil) 21 | recorder := httptest.NewRecorder() 22 | recorder.Body = dst 23 | 24 | for _, d := range testdata { 25 | src := bytes.NewBuffer([]byte(d)) 26 | dst.Reset() 27 | err := h.copyResponse(recorder, src, 0, caddy.Log()) 28 | if err != nil { 29 | t.Errorf("failed with error: %v", err) 30 | } 31 | out := dst.String() 32 | if out != d { 33 | t.Errorf("bad read: got %q", out) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /modules/caddyhttp/reverseproxy/upstreams_test.go: -------------------------------------------------------------------------------- 1 | package reverseproxy 2 | 3 | import "testing" 4 | 5 | func TestResolveIpVersion(t *testing.T) { 6 | falseBool := false 7 | trueBool := true 8 | tests := []struct { 9 | Versions *IPVersions 10 | expectedIpVersion string 11 | }{ 12 | { 13 | Versions: &IPVersions{IPv4: &trueBool}, 14 | expectedIpVersion: "ip4", 15 | }, 16 | { 17 | Versions: &IPVersions{IPv4: &falseBool}, 18 | expectedIpVersion: "ip", 19 | }, 20 | { 21 | Versions: &IPVersions{IPv4: &trueBool, IPv6: &falseBool}, 22 | expectedIpVersion: "ip4", 23 | }, 24 | { 25 | Versions: &IPVersions{IPv6: &trueBool}, 26 | expectedIpVersion: "ip6", 27 | }, 28 | { 29 | Versions: &IPVersions{IPv6: &falseBool}, 30 | expectedIpVersion: "ip", 31 | }, 32 | { 33 | Versions: &IPVersions{IPv6: &trueBool, IPv4: &falseBool}, 34 | expectedIpVersion: "ip6", 35 | }, 36 | { 37 | Versions: &IPVersions{}, 38 | expectedIpVersion: "ip", 39 | }, 40 | { 41 | Versions: &IPVersions{IPv4: &trueBool, IPv6: &trueBool}, 42 | expectedIpVersion: "ip", 43 | }, 44 | { 45 | Versions: &IPVersions{IPv4: &falseBool, IPv6: &falseBool}, 46 | expectedIpVersion: "ip", 47 | }, 48 | } 49 | for _, test := range tests { 50 | ipVersion := resolveIpVersion(test.Versions) 51 | if ipVersion != test.expectedIpVersion { 52 | t.Errorf("resolveIpVersion(): Expected %s got %s", test.expectedIpVersion, ipVersion) 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /modules/caddyhttp/standard/imports.go: -------------------------------------------------------------------------------- 1 | package standard 2 | 3 | import ( 4 | // standard Caddy HTTP app modules 5 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp" 6 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/caddyauth" 7 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/encode" 8 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/encode/brotli" 9 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/encode/gzip" 10 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/encode/zstd" 11 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/fileserver" 12 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/headers" 13 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/intercept" 14 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/logging" 15 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/map" 16 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/proxyprotocol" 17 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/push" 18 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/requestbody" 19 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy" 20 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy/fastcgi" 21 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy/forwardauth" 22 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/rewrite" 23 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/templates" 24 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/tracing" 25 | ) 26 | -------------------------------------------------------------------------------- /modules/caddyhttp/templates/frontmatter_fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build gofuzz 16 | 17 | package templates 18 | 19 | func FuzzExtractFrontMatter(data []byte) int { 20 | _, _, err := extractFrontMatter(string(data)) 21 | if err != nil { 22 | return 0 23 | } 24 | return 1 25 | } 26 | -------------------------------------------------------------------------------- /modules/caddyhttp/tracing/tracer_test.go: -------------------------------------------------------------------------------- 1 | package tracing 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/caddyserver/caddy/v2" 8 | ) 9 | 10 | func TestOpenTelemetryWrapper_newOpenTelemetryWrapper(t *testing.T) { 11 | ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()}) 12 | defer cancel() 13 | 14 | var otw openTelemetryWrapper 15 | var err error 16 | 17 | if otw, err = newOpenTelemetryWrapper(ctx, 18 | "", 19 | ); err != nil { 20 | t.Errorf("newOpenTelemetryWrapper() error = %v", err) 21 | t.FailNow() 22 | } 23 | 24 | if otw.propagators == nil { 25 | t.Errorf("Propagators should not be empty") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /modules/caddyhttp/tracing/tracerprovider_test.go: -------------------------------------------------------------------------------- 1 | package tracing 2 | 3 | import ( 4 | "testing" 5 | 6 | "go.uber.org/zap" 7 | ) 8 | 9 | func Test_tracersProvider_getTracerProvider(t *testing.T) { 10 | tp := tracerProvider{} 11 | 12 | tp.getTracerProvider() 13 | tp.getTracerProvider() 14 | 15 | if tp.tracerProvider == nil { 16 | t.Errorf("There should be tracer provider") 17 | } 18 | 19 | if tp.tracerProvidersCounter != 2 { 20 | t.Errorf("Tracer providers counter should equal to 2") 21 | } 22 | } 23 | 24 | func Test_tracersProvider_cleanupTracerProvider(t *testing.T) { 25 | tp := tracerProvider{} 26 | 27 | tp.getTracerProvider() 28 | tp.getTracerProvider() 29 | 30 | err := tp.cleanupTracerProvider(zap.NewNop()) 31 | if err != nil { 32 | t.Errorf("There should be no error: %v", err) 33 | } 34 | 35 | if tp.tracerProvider == nil { 36 | t.Errorf("There should be tracer provider") 37 | } 38 | 39 | if tp.tracerProvidersCounter != 1 { 40 | t.Errorf("Tracer providers counter should equal to 1") 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /modules/caddytls/leaffileloader_test.go: -------------------------------------------------------------------------------- 1 | package caddytls 2 | 3 | import ( 4 | "context" 5 | "encoding/pem" 6 | "os" 7 | "strings" 8 | "testing" 9 | 10 | "github.com/caddyserver/caddy/v2" 11 | ) 12 | 13 | func TestLeafFileLoader(t *testing.T) { 14 | fl := LeafFileLoader{Files: []string{"../../caddytest/leafcert.pem"}} 15 | fl.Provision(caddy.Context{Context: context.Background()}) 16 | 17 | out, err := fl.LoadLeafCertificates() 18 | if err != nil { 19 | t.Errorf("Leaf certs file loading test failed: %v", err) 20 | } 21 | if len(out) != 1 { 22 | t.Errorf("Error loading leaf cert in memory struct") 23 | return 24 | } 25 | pemBytes := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: out[0].Raw}) 26 | 27 | pemFileBytes, err := os.ReadFile("../../caddytest/leafcert.pem") 28 | if err != nil { 29 | t.Errorf("Unable to read the example certificate from the file") 30 | } 31 | 32 | // Remove /r because windows. 33 | pemFileString := strings.ReplaceAll(string(pemFileBytes), "\r\n", "\n") 34 | 35 | if string(pemBytes) != pemFileString { 36 | t.Errorf("Leaf Certificate File Loader: Failed to load the correct certificate") 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /modules/caddytls/leaffolderloader_test.go: -------------------------------------------------------------------------------- 1 | package caddytls 2 | 3 | import ( 4 | "context" 5 | "encoding/pem" 6 | "os" 7 | "strings" 8 | "testing" 9 | 10 | "github.com/caddyserver/caddy/v2" 11 | ) 12 | 13 | func TestLeafFolderLoader(t *testing.T) { 14 | fl := LeafFolderLoader{Folders: []string{"../../caddytest"}} 15 | fl.Provision(caddy.Context{Context: context.Background()}) 16 | 17 | out, err := fl.LoadLeafCertificates() 18 | if err != nil { 19 | t.Errorf("Leaf certs folder loading test failed: %v", err) 20 | } 21 | if len(out) != 1 { 22 | t.Errorf("Error loading leaf cert in memory struct") 23 | return 24 | } 25 | pemBytes := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: out[0].Raw}) 26 | pemFileBytes, err := os.ReadFile("../../caddytest/leafcert.pem") 27 | if err != nil { 28 | t.Errorf("Unable to read the example certificate from the file") 29 | } 30 | 31 | // Remove /r because windows. 32 | pemFileString := strings.ReplaceAll(string(pemFileBytes), "\r\n", "\n") 33 | 34 | if string(pemBytes) != pemFileString { 35 | t.Errorf("Leaf Certificate Folder Loader: Failed to load the correct certificate") 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /modules/caddytls/leafpemloader_test.go: -------------------------------------------------------------------------------- 1 | package caddytls 2 | 3 | import ( 4 | "context" 5 | "encoding/pem" 6 | "os" 7 | "strings" 8 | "testing" 9 | 10 | "github.com/caddyserver/caddy/v2" 11 | ) 12 | 13 | func TestLeafPEMLoader(t *testing.T) { 14 | pl := LeafPEMLoader{Certificates: []string{` 15 | -----BEGIN CERTIFICATE----- 16 | MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL 17 | MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC 18 | VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx 19 | NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD 20 | TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu 21 | ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j 22 | V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj 23 | gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA 24 | FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE 25 | CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS 26 | BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE 27 | BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju 28 | Wm7DCfrPNGVwFWUQOmsPue9rZBgO 29 | -----END CERTIFICATE----- 30 | `}} 31 | pl.Provision(caddy.Context{Context: context.Background()}) 32 | 33 | out, err := pl.LoadLeafCertificates() 34 | if err != nil { 35 | t.Errorf("Leaf certs pem loading test failed: %v", err) 36 | } 37 | if len(out) != 1 { 38 | t.Errorf("Error loading leaf cert in memory struct") 39 | return 40 | } 41 | pemBytes := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: out[0].Raw}) 42 | 43 | pemFileBytes, err := os.ReadFile("../../caddytest/leafcert.pem") 44 | if err != nil { 45 | t.Errorf("Unable to read the example certificate from the file") 46 | } 47 | 48 | // Remove /r because windows. 49 | pemFileString := strings.ReplaceAll(string(pemFileBytes), "\r\n", "\n") 50 | 51 | if string(pemBytes) != pemFileString { 52 | t.Errorf("Leaf Certificate Folder Loader: Failed to load the correct certificate") 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /modules/logging/cores.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import ( 4 | "go.uber.org/zap/zapcore" 5 | 6 | "github.com/caddyserver/caddy/v2" 7 | "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" 8 | ) 9 | 10 | func init() { 11 | caddy.RegisterModule(MockCore{}) 12 | } 13 | 14 | // MockCore is a no-op module, purely for testing 15 | type MockCore struct { 16 | zapcore.Core `json:"-"` 17 | } 18 | 19 | // CaddyModule returns the Caddy module information. 20 | func (MockCore) CaddyModule() caddy.ModuleInfo { 21 | return caddy.ModuleInfo{ 22 | ID: "caddy.logging.cores.mock", 23 | New: func() caddy.Module { return new(MockCore) }, 24 | } 25 | } 26 | 27 | func (lec *MockCore) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { 28 | return nil 29 | } 30 | 31 | // Interface guards 32 | var ( 33 | _ zapcore.Core = (*MockCore)(nil) 34 | _ caddy.Module = (*MockCore)(nil) 35 | _ caddyfile.Unmarshaler = (*MockCore)(nil) 36 | ) 37 | -------------------------------------------------------------------------------- /modules/logging/filewriter_test_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build windows 16 | 17 | package logging 18 | 19 | import ( 20 | "os" 21 | "path" 22 | "testing" 23 | ) 24 | 25 | // Windows relies on ACLs instead of unix permissions model. 26 | // Go allows to open files with a particular mode put it is limited to read or write. 27 | // See https://cs.opensource.google/go/go/+/refs/tags/go1.22.3:src/syscall/syscall_windows.go;l=708. 28 | // This is pretty restrictive and has few interest for log files and thus we just test that log files are 29 | // opened with R/W permissions by default on Windows too. 30 | func TestFileCreationMode(t *testing.T) { 31 | dir, err := os.MkdirTemp("", "caddytest") 32 | if err != nil { 33 | t.Fatalf("failed to create tempdir: %v", err) 34 | } 35 | defer os.RemoveAll(dir) 36 | 37 | fw := &FileWriter{ 38 | Filename: path.Join(dir, "test.log"), 39 | } 40 | 41 | logger, err := fw.OpenWriter() 42 | if err != nil { 43 | t.Fatalf("failed to create file: %v", err) 44 | } 45 | defer logger.Close() 46 | 47 | st, err := os.Stat(fw.Filename) 48 | if err != nil { 49 | t.Fatalf("failed to check file permissions: %v", err) 50 | } 51 | 52 | if st.Mode().Perm()&0o600 != 0o600 { 53 | t.Fatalf("file mode is %v, want rw for user", st.Mode().Perm()) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /modules/metrics/metrics_test.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" 7 | ) 8 | 9 | func TestMetricsUnmarshalCaddyfile(t *testing.T) { 10 | m := &Metrics{} 11 | d := caddyfile.NewTestDispenser(`metrics bogus`) 12 | err := m.UnmarshalCaddyfile(d) 13 | if err == nil { 14 | t.Errorf("expected error") 15 | } 16 | 17 | m = &Metrics{} 18 | d = caddyfile.NewTestDispenser(`metrics`) 19 | err = m.UnmarshalCaddyfile(d) 20 | if err != nil { 21 | t.Errorf("unexpected error: %v", err) 22 | } 23 | 24 | if m.DisableOpenMetrics { 25 | t.Errorf("DisableOpenMetrics should've been false: %v", m.DisableOpenMetrics) 26 | } 27 | 28 | m = &Metrics{} 29 | d = caddyfile.NewTestDispenser(`metrics { disable_openmetrics }`) 30 | err = m.UnmarshalCaddyfile(d) 31 | if err != nil { 32 | t.Errorf("unexpected error: %v", err) 33 | } 34 | 35 | if !m.DisableOpenMetrics { 36 | t.Errorf("DisableOpenMetrics should've been true: %v", m.DisableOpenMetrics) 37 | } 38 | 39 | m = &Metrics{} 40 | d = caddyfile.NewTestDispenser(`metrics { bogus }`) 41 | err = m.UnmarshalCaddyfile(d) 42 | if err == nil { 43 | t.Errorf("expected error: %v", err) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /modules/standard/imports.go: -------------------------------------------------------------------------------- 1 | package standard 2 | 3 | import ( 4 | // standard Caddy modules 5 | _ "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" 6 | _ "github.com/caddyserver/caddy/v2/modules/caddyevents" 7 | _ "github.com/caddyserver/caddy/v2/modules/caddyevents/eventsconfig" 8 | _ "github.com/caddyserver/caddy/v2/modules/caddyfs" 9 | _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/standard" 10 | _ "github.com/caddyserver/caddy/v2/modules/caddypki" 11 | _ "github.com/caddyserver/caddy/v2/modules/caddypki/acmeserver" 12 | _ "github.com/caddyserver/caddy/v2/modules/caddytls" 13 | _ "github.com/caddyserver/caddy/v2/modules/caddytls/distributedstek" 14 | _ "github.com/caddyserver/caddy/v2/modules/caddytls/standardstek" 15 | _ "github.com/caddyserver/caddy/v2/modules/filestorage" 16 | _ "github.com/caddyserver/caddy/v2/modules/logging" 17 | _ "github.com/caddyserver/caddy/v2/modules/metrics" 18 | ) 19 | -------------------------------------------------------------------------------- /notify/notify_other.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build !linux && !windows 16 | 17 | package notify 18 | 19 | func Ready() error { return nil } 20 | func Reloading() error { return nil } 21 | func Stopping() error { return nil } 22 | func Status(_ string) error { return nil } 23 | func Error(_ error, _ int) error { return nil } 24 | -------------------------------------------------------------------------------- /notify/notify_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package notify 16 | 17 | import "golang.org/x/sys/windows/svc" 18 | 19 | // globalStatus store windows service status, it can be 20 | // use to notify caddy status. 21 | var globalStatus chan<- svc.Status 22 | 23 | func SetGlobalStatus(status chan<- svc.Status) { 24 | globalStatus = status 25 | } 26 | 27 | func Ready() error { 28 | if globalStatus != nil { 29 | globalStatus <- svc.Status{ 30 | State: svc.Running, 31 | Accepts: svc.AcceptStop | svc.AcceptShutdown, 32 | } 33 | } 34 | return nil 35 | } 36 | 37 | func Reloading() error { 38 | if globalStatus != nil { 39 | globalStatus <- svc.Status{State: svc.StartPending} 40 | } 41 | return nil 42 | } 43 | 44 | func Stopping() error { 45 | if globalStatus != nil { 46 | globalStatus <- svc.Status{State: svc.StopPending} 47 | } 48 | return nil 49 | } 50 | 51 | // TODO: not implemented 52 | func Status(_ string) error { return nil } 53 | 54 | // TODO: not implemented 55 | func Error(_ error, _ int) error { return nil } 56 | -------------------------------------------------------------------------------- /replacer_fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build gofuzz 16 | 17 | package caddy 18 | 19 | func FuzzReplacer(data []byte) (score int) { 20 | NewReplacer().ReplaceAll(string(data), "") 21 | NewReplacer().ReplaceAll(NewReplacer().ReplaceAll(string(data), ""), "") 22 | NewReplacer().ReplaceAll(NewReplacer().ReplaceAll(string(data), ""), NewReplacer().ReplaceAll(string(data), "")) 23 | NewReplacer().ReplaceAll(string(data[:len(data)/2]), string(data[len(data)/2:])) 24 | return 0 25 | } 26 | -------------------------------------------------------------------------------- /service_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package caddy 16 | 17 | import ( 18 | "os" 19 | "path/filepath" 20 | 21 | "golang.org/x/sys/windows/svc" 22 | 23 | "github.com/caddyserver/caddy/v2/notify" 24 | ) 25 | 26 | func init() { 27 | isService, err := svc.IsWindowsService() 28 | if err != nil || !isService { 29 | return 30 | } 31 | 32 | // Windows services always start in the system32 directory, try to 33 | // switch into the directory where the caddy executable is. 34 | execPath, err := os.Executable() 35 | if err == nil { 36 | _ = os.Chdir(filepath.Dir(execPath)) 37 | } 38 | 39 | go func() { 40 | _ = svc.Run("", runner{}) 41 | }() 42 | } 43 | 44 | type runner struct{} 45 | 46 | func (runner) Execute(args []string, request <-chan svc.ChangeRequest, status chan<- svc.Status) (bool, uint32) { 47 | notify.SetGlobalStatus(status) 48 | status <- svc.Status{State: svc.StartPending} 49 | 50 | for { 51 | req := <-request 52 | switch req.Cmd { 53 | case svc.Interrogate: 54 | status <- req.CurrentStatus 55 | case svc.Stop, svc.Shutdown: 56 | status <- svc.Status{State: svc.StopPending} 57 | exitProcessFromSignal("SIGINT") 58 | return false, 0 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /sigtrap_nonposix.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Matthew Holt and The Caddy Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //go:build windows || plan9 || nacl || js 16 | 17 | package caddy 18 | 19 | func trapSignalsPosix() {} 20 | --------------------------------------------------------------------------------