{"action":"created","issue":{"url":"https://api.github.com/repos/mholt/caddy/issues/619","repository_url":"https://api.github.com/repos/mholt/caddy","labels_url":"https://api.github.com/repos/mholt/caddy/issues/619/labels{/name}","comments_url":"https://api.github.com/repos/mholt/caddy/issues/619/comments","events_url":"https://api.github.com/repos/mholt/caddy/issues/619/events","html_url":"https://github.com/mholt/caddy/issues/619","id":135120665,"number":619,"title":"Proposal: Upgrades to the Caddyfile","user":{"login":"mholt","id":1128849,"avatar_url":"https://avatars.githubusercontent.com/u/1128849?v=3","gravatar_id":"","url":"https://api.github.com/users/mholt","html_url":"https://github.com/mholt","followers_url":"https://api.github.com/users/mholt/followers","following_url":"https://api.github.com/users/mholt/following{/other_user}","gists_url":"https://api.github.com/users/mholt/gists{/gist_id}","starred_url":"https://api.github.com/users/mholt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mholt/subscriptions","organizations_url":"https://api.github.com/users/mholt/orgs","repos_url":"https://api.github.com/users/mholt/repos","events_url":"https://api.github.com/users/mholt/events{/privacy}","received_events_url":"https://api.github.com/users/mholt/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/mholt/caddy/labels/discussion","name":"discussion","color":"006b75"},{"url":"https://api.github.com/repos/mholt/caddy/labels/help%20wanted","name":"help wanted","color":"159818"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":25,"created_at":"2016-02-20T21:06:40Z","updated_at":"2016-03-08T17:14:23Z","closed_at":null,"body":"A number of issues (#587, #566, #310, #167, #103, and *maybe* #584 and #209) and discussions [in gitter chat](https://gitter.im/mholt/caddy) have some things in common: they want to match requests by more than just the path prefix, and they want to be able to use variable or pre-defined values elsewhere in the Caddyfile.\r\n\r\nIn an attempt to *mostly* resolve *most* of those issues, I propose a few changes/upgrades to the Caddyfile.\r\n\r\n### 1. More powerful path matching\r\n\r\nRight now, most directives only accept a base path to match:\r\n\r\n```plain\r\nredir /foo https://sub.example.com/foo\r\n```\r\n\r\nIf we replace `/foo` (the base path) with a more expressive matching block, we can meet most users' needs. For example:\r\n\r\n```plain\r\nredir {\r\n    {path} not /\r\n    and {>Referer} has google.com or {>Referer} has bing.com\r\n} https://sub.example.com{uri}\r\n```\r\n\r\nNotice here that we've specified three conditions, where the last two are grouped because they are on the same line. We're using [placeholders](https://caddyserver.com/docs/placeholders) for the dynamic values. It is the equivalent of this pseudocode:\r\n\r\n```go\r\nreq.URL.Path != \"/\" && (strings.Contains(header[\"Referer\"], \"google.com\") || strings.Contains(header[\"Referer\"], \"bing.com\")\r\n```\r\n\r\n### 2. Virtual hosts defined by more than an explicit host:port\r\n\r\nWe've had numerous requests for variable site roots, but [that's](https://github.com/mholt/caddy/issues/167#issuecomment-176822199) complicated since some directives need to know the site root when the server starts.\r\n\r\nSo how about we describe \"virtual hosts\" not so much as a `host:port` but as a \"site\" instead, and sites can be defined with wildcards and even request paths:\r\n\r\n```\r\n# What you're used to: a server block is headed by a host name\r\nexample.com {\r\n    root /www/example.com\r\n}\r\n\r\n# But you could specify a path to have variable roots\r\nexample.com/foo {\r\n    root /www/foo\r\n}\r\nexample.com/bar {\r\n    root /www/bar\r\n}\r\n\r\n# You could also use wildcards\r\n# (but the *-value would not be accessible by a placeholder)\r\n*.example.com {\r\n    root /www/sub.example.com\r\n}\r\n```\r\n\r\nHowever, if wildcards are used in a hostname, we are not able to issue certificates for those names. Even if Let's Encrypt enabled wildcard issuance, we wouldn't be able to issue certificates for `example*.com`, at least, not until Caddy gets On-Demand TLS (which issues certificates during the TLS handshake, about which I'm in talks with Let's Encrypt right now, hoping they'll let me do it).\r\n\r\n### 3. Re-using blocks and arguments\r\n\r\nThere have been some requests for variables. I'd like to know more about why environment variables and current placeholders will not suffice. I feel strongly that once we introduce memory into the Caddyfile it creeps ever closer to a programming language, or at least some sort of interpreted script. I like it simplicity right now. A lot. That was kind of the point of making Caddy.\r\n\r\n\r\n### A note on philosophy\r\n\r\nThese proposed changes go slightly against my better judgment, since the Caddyfile encourages well-architected websites and web applications that use paths to clearly define content and behavior, rather than invoking the complexities of HTTP when it is avoidable by simply organizing resources by path rather than by creating all sorts of complex conditions. Frankly, if your web server behavior has to be scripted, you might as well just write one with a real programming language anyway and gain the full benefits of mature tools, a turing-complete language, etc.\r\n\r\nThese changes considerably raise the complexity of the config-related code, but it might be a net savings in the long run, rather than trying ad-hoc solutions. I also want to help grow Caddy's adoption rate. But know that at the moment, I'm disinclined to implement these changes unless I can be convinced this is the best way to go. Changes have to be in-line with the Caddy philosophy of simplicity and ease of use.\r\n\r\nI'm not promising any of these changes but I wanted to funnel the discussion of all those issues into here. As such, I'm closing those issues but encourage you to reference them for historical purposes, so you can glean a richer understanding of the problems we're trying to solve.\r\n\r\n### When you reply here...\r\n\r\nThere are 3 topics in this one issue but all involve a near-complete rewrite in how we parse and execute the Caddyfile. Please be specific about which topic you're referring to (1, 2, or 3), and use inline quotes and proper formatting to preserve context. Thanks!"},"comment":{"url":"https://api.github.com/repos/mholt/caddy/issues/comments/193874292","html_url":"https://github.com/mholt/caddy/issues/619#issuecomment-193874292","issue_url":"https://api.github.com/repos/mholt/caddy/issues/619","id":193874292,"user":{"login":"jacobhands","id":10719325,"avatar_url":"https://avatars.githubusercontent.com/u/10719325?v=3","gravatar_id":"","url":"https://api.github.com/users/jacobhands","html_url":"https://github.com/jacobhands","followers_url":"https://api.github.com/users/jacobhands/followers","following_url":"https://api.github.com/users/jacobhands/following{/other_user}","gists_url":"https://api.github.com/users/jacobhands/gists{/gist_id}","starred_url":"https://api.github.com/users/jacobhands/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jacobhands/subscriptions","organizations_url":"https://api.github.com/users/jacobhands/orgs","repos_url":"https://api.github.com/users/jacobhands/repos","events_url":"https://api.github.com/users/jacobhands/events{/privacy}","received_events_url":"https://api.github.com/users/jacobhands/received_events","type":"User","site_admin":false},"created_at":"2016-03-08T17:14:23Z","updated_at":"2016-03-08T17:14:23Z","body":"Wildcards should only apply to a single label.\r\n```\r\n*.example.com {}\r\n*.foo.example.com {\r\n    # does not inherit from *.example.com\r\n}\r\n```"}}