Yesod: Dynamic subdomains

Hi, I am building a Yesod web app which should support dynamic subdomains. I.e. a user registers as "foobar" on http://www.example.com and can afterwards access her content via http://foobar.example.com Is this possible at all? I am wondering, because the server name is somehow hard coded in Settings.hs as approot. If it is possible: How do I access the domain name in a handler function? Thanks! Timo

On Fri, Aug 26, 2011 at 4:09 PM, "Timo B. Hübel"
Hi,
I am building a Yesod web app which should support dynamic subdomains. I.e. a user registers as "foobar" on http://www.example.com and can afterwards access her content via http://foobar.example.com
Is this possible at all? I am wondering, because the server name is somehow hard coded in Settings.hs as approot.
If it is possible: How do I access the domain name in a handler function?
Thanks! Timo
Hi Timo, I've put up a cookbook recipe for domain-based routing[1]. It doesn't require checking domain names in the handler function at all, but instead uses the normal routing mechanism in Yesod. As a direct answer to your question, to get access to the domain name, you'll want to get the WAI request value via waiRequest[2] and then lookup the "Host" header in requestHeaders[3]. Let's direct any follow-up discussion to the Yesod mailing list (CCed). Michael [1] http://www.yesodweb.com/wiki/Domain-based%20routing [2] http://hackage.haskell.org/packages/archive/yesod-core/0.8.3.2/doc/html/Yeso... [3] http://hackage.haskell.org/packages/archive/wai/0.4.1/doc/html/Network-Wai.h...

Great example! Inspired me to post a recipe for re-directing from www to the
main domain: http://www.yesodweb.com/show/topic/536
Did the syntax high-lighting stylesheet disappear?
The domain-based routing does make me wonder though- in Rack the data
structure is a hash instead of a record and I could place the sub-domain
somewhere in the hash. Having a reliable record is much nicer than a hash.
However, this shows a use-case where we want to save off extra data at the
WAI level, but there is no way to do so. It seems like WAI should be
modified in some way to properly accommodate this use case. The first thing
that comes to my mind is having an extra parameter in the request record
that is a Map expressly for the purpose of storing data for later use. What
do you think?
Greg Weber
On Sat, Aug 27, 2011 at 11:09 AM, Michael Snoyman
On Fri, Aug 26, 2011 at 4:09 PM, "Timo B. Hübel"
wrote: Hi,
I am building a Yesod web app which should support dynamic subdomains. I.e. a user registers as "foobar" on http://www.example.com and can afterwards access her content via http://foobar.example.com
Is this possible at all? I am wondering, because the server name is somehow hard coded in Settings.hs as approot.
If it is possible: How do I access the domain name in a handler function?
Thanks! Timo
Hi Timo,
I've put up a cookbook recipe for domain-based routing[1]. It doesn't require checking domain names in the handler function at all, but instead uses the normal routing mechanism in Yesod. As a direct answer to your question, to get access to the domain name, you'll want to get the WAI request value via waiRequest[2] and then lookup the "Host" header in requestHeaders[3].
Let's direct any follow-up discussion to the Yesod mailing list (CCed).
Michael
[1] http://www.yesodweb.com/wiki/Domain-based%20routing [2] http://hackage.haskell.org/packages/archive/yesod-core/0.8.3.2/doc/html/Yeso... [3] http://hackage.haskell.org/packages/archive/wai/0.4.1/doc/html/Network-Wai.h...

The stylesheet: Pandoc compiled without -fhighlighting (as we both
knew would happen eventually ;)). I'm recompiling and uploading a new
copy now.
I don't really think this has anything to do with WAI. Firstly, I was
mistaken in using the Host request header, WAI already provides a
serverName record in the Request datatype, I'd simply forgotten about
it. The routing issue is that Yesod only pays attention to the path
info for routing, so we're "hacking" WAI to expose extra information
in that record that wouldn't normally be there. I think the real
question is if Yesod needs to be modified to allow routing on
something else, but I think that:
1. We've optimized for the common case, and any deviation from what
we've done will make normal usage of Yesod much more difficult.
2. Even though this is a hack, it's not a particularly bad one, and
all normal Yesod features like type-safe URLs and declarative routing
still work without a hitch.
Michael
On Sat, Aug 27, 2011 at 9:56 PM, Greg Weber
Great example! Inspired me to post a recipe for re-directing from www to the main domain: http://www.yesodweb.com/show/topic/536 Did the syntax high-lighting stylesheet disappear?
The domain-based routing does make me wonder though- in Rack the data structure is a hash instead of a record and I could place the sub-domain somewhere in the hash. Having a reliable record is much nicer than a hash. However, this shows a use-case where we want to save off extra data at the WAI level, but there is no way to do so. It seems like WAI should be modified in some way to properly accommodate this use case. The first thing that comes to my mind is having an extra parameter in the request record that is a Map expressly for the purpose of storing data for later use. What do you think? Greg Weber
On Sat, Aug 27, 2011 at 11:09 AM, Michael Snoyman
wrote: On Fri, Aug 26, 2011 at 4:09 PM, "Timo B. Hübel"
wrote: Hi,
I am building a Yesod web app which should support dynamic subdomains. I.e. a user registers as "foobar" on http://www.example.com and can afterwards access her content via http://foobar.example.com
Is this possible at all? I am wondering, because the server name is somehow hard coded in Settings.hs as approot.
If it is possible: How do I access the domain name in a handler function?
Thanks! Timo
Hi Timo,
I've put up a cookbook recipe for domain-based routing[1]. It doesn't require checking domain names in the handler function at all, but instead uses the normal routing mechanism in Yesod. As a direct answer to your question, to get access to the domain name, you'll want to get the WAI request value via waiRequest[2] and then lookup the "Host" header in requestHeaders[3].
Let's direct any follow-up discussion to the Yesod mailing list (CCed).
Michael
[1] http://www.yesodweb.com/wiki/Domain-based%20routing [2] http://hackage.haskell.org/packages/archive/yesod-core/0.8.3.2/doc/html/Yeso... [3] http://hackage.haskell.org/packages/archive/wai/0.4.1/doc/html/Network-Wai.h...

I agree that WAI is well optimized for the common use case, and that this
particular use case may call for a change in Yesod rather than WAI. However,
not being able to store arbitrary data does limit what can be achieved in
WAI.
In Ruby there things (like authentication) that are being done in Rack that
would be difficult to achieve in an extensible way without that capability.
WAI may not seem like the correct layer for those kinds of features.
However, in an environment like Ruby where there *every* web framework uses
Rack, there is a lot of advantage that can be gained by pushing core
features down there.
On Sat, Aug 27, 2011 at 12:10 PM, Michael Snoyman
The stylesheet: Pandoc compiled without -fhighlighting (as we both knew would happen eventually ;)). I'm recompiling and uploading a new copy now.
I don't really think this has anything to do with WAI. Firstly, I was mistaken in using the Host request header, WAI already provides a serverName record in the Request datatype, I'd simply forgotten about it. The routing issue is that Yesod only pays attention to the path info for routing, so we're "hacking" WAI to expose extra information in that record that wouldn't normally be there. I think the real question is if Yesod needs to be modified to allow routing on something else, but I think that:
1. We've optimized for the common case, and any deviation from what we've done will make normal usage of Yesod much more difficult. 2. Even though this is a hack, it's not a particularly bad one, and all normal Yesod features like type-safe URLs and declarative routing still work without a hitch.
Michael
Great example! Inspired me to post a recipe for re-directing from www to
main domain: http://www.yesodweb.com/show/topic/536 Did the syntax high-lighting stylesheet disappear?
The domain-based routing does make me wonder though- in Rack the data structure is a hash instead of a record and I could place the sub-domain somewhere in the hash. Having a reliable record is much nicer than a hash. However, this shows a use-case where we want to save off extra data at
WAI level, but there is no way to do so. It seems like WAI should be modified in some way to properly accommodate this use case. The first
On Sat, Aug 27, 2011 at 9:56 PM, Greg Weber
wrote: the the thing that comes to my mind is having an extra parameter in the request record that is a Map expressly for the purpose of storing data for later use. What do you think? Greg Weber
On Sat, Aug 27, 2011 at 11:09 AM, Michael Snoyman
wrote: On Fri, Aug 26, 2011 at 4:09 PM, "Timo B. Hübel"
wrote: Hi,
I am building a Yesod web app which should support dynamic subdomains. I.e. a user registers as "foobar" on http://www.example.com and can afterwards access her content via http://foobar.example.com
Is this possible at all? I am wondering, because the server name is somehow hard coded in Settings.hs as approot.
If it is possible: How do I access the domain name in a handler function?
Thanks! Timo
Hi Timo,
I've put up a cookbook recipe for domain-based routing[1]. It doesn't require checking domain names in the handler function at all, but instead uses the normal routing mechanism in Yesod. As a direct answer to your question, to get access to the domain name, you'll want to get the WAI request value via waiRequest[2] and then lookup the "Host" header in requestHeaders[3].
Let's direct any follow-up discussion to the Yesod mailing list (CCed).
Michael
http://hackage.haskell.org/packages/archive/yesod-core/0.8.3.2/doc/html/Yeso...
[3]
http://hackage.haskell.org/packages/archive/wai/0.4.1/doc/html/Network-Wai.h...

I think that the better approach to this is something along the lines
of CleanPath[1] (which is horribly documented btw). Instead of just
having some arbitrary Map in the Request value, we explicitly pass
extra data to the Application.
[1] http://hackage.haskell.org/packages/archive/wai-extra/0.4.1.2/doc/html/Netwo...
On Sat, Aug 27, 2011 at 11:14 PM, Greg Weber
I agree that WAI is well optimized for the common use case, and that this particular use case may call for a change in Yesod rather than WAI. However, not being able to store arbitrary data does limit what can be achieved in WAI. In Ruby there things (like authentication) that are being done in Rack that would be difficult to achieve in an extensible way without that capability. WAI may not seem like the correct layer for those kinds of features. However, in an environment like Ruby where there *every* web framework uses Rack, there is a lot of advantage that can be gained by pushing core features down there. On Sat, Aug 27, 2011 at 12:10 PM, Michael Snoyman
wrote: The stylesheet: Pandoc compiled without -fhighlighting (as we both knew would happen eventually ;)). I'm recompiling and uploading a new copy now.
I don't really think this has anything to do with WAI. Firstly, I was mistaken in using the Host request header, WAI already provides a serverName record in the Request datatype, I'd simply forgotten about it. The routing issue is that Yesod only pays attention to the path info for routing, so we're "hacking" WAI to expose extra information in that record that wouldn't normally be there. I think the real question is if Yesod needs to be modified to allow routing on something else, but I think that:
1. We've optimized for the common case, and any deviation from what we've done will make normal usage of Yesod much more difficult. 2. Even though this is a hack, it's not a particularly bad one, and all normal Yesod features like type-safe URLs and declarative routing still work without a hitch.
Michael
On Sat, Aug 27, 2011 at 9:56 PM, Greg Weber
wrote: Great example! Inspired me to post a recipe for re-directing from www to the main domain: http://www.yesodweb.com/show/topic/536 Did the syntax high-lighting stylesheet disappear?
The domain-based routing does make me wonder though- in Rack the data structure is a hash instead of a record and I could place the sub-domain somewhere in the hash. Having a reliable record is much nicer than a hash. However, this shows a use-case where we want to save off extra data at the WAI level, but there is no way to do so. It seems like WAI should be modified in some way to properly accommodate this use case. The first thing that comes to my mind is having an extra parameter in the request record that is a Map expressly for the purpose of storing data for later use. What do you think? Greg Weber
On Sat, Aug 27, 2011 at 11:09 AM, Michael Snoyman
wrote: On Fri, Aug 26, 2011 at 4:09 PM, "Timo B. Hübel"
wrote: Hi,
I am building a Yesod web app which should support dynamic subdomains. I.e. a user registers as "foobar" on http://www.example.com and can afterwards access her content via http://foobar.example.com
Is this possible at all? I am wondering, because the server name is somehow hard coded in Settings.hs as approot.
If it is possible: How do I access the domain name in a handler function?
Thanks! Timo
Hi Timo,
I've put up a cookbook recipe for domain-based routing[1]. It doesn't require checking domain names in the handler function at all, but instead uses the normal routing mechanism in Yesod. As a direct answer to your question, to get access to the domain name, you'll want to get the WAI request value via waiRequest[2] and then lookup the "Host" header in requestHeaders[3].
Let's direct any follow-up discussion to the Yesod mailing list (CCed).
Michael
[1] http://www.yesodweb.com/wiki/Domain-based%20routing [2]
http://hackage.haskell.org/packages/archive/yesod-core/0.8.3.2/doc/html/Yeso... [3]
http://hackage.haskell.org/packages/archive/wai/0.4.1/doc/html/Network-Wai.h...
participants (3)
-
"Timo B. Hübel"
-
Greg Weber
-
Michael Snoyman