Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to capture a path segment optionally? (was: Any reason why CaptureHint is not exported?) #1795

Open
saurabhnanda opened this issue Dec 1, 2024 · 5 comments

Comments

@saurabhnanda
Copy link

saurabhnanda commented Dec 1, 2024

I am knee-deep into finding a solution for How to optionally capture a path segment in Haskell servant? and I think I have hit upon something that could work (given below) BUT it won't compile without access to Servant.Server.Internal.Router.CaptureHint. Any reason why it has not been exported? Without access to that type, is there any other way to use addCapture?

data HostWithLocale = HostWithLocale

instance (HasServer api context) => HasServer (HostWithLocale :> api) context where
  type ServerT (HostWithLocale :> api) m = (Hostname, Maybe LanguageCode) -> ServerT api m
  
  hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt . s  

  route _ context server = 
    CaptureRouter [hint] $ route (Proxy :: Proxy api) context subserver
    where
      hint = CaptureHint "language" (typeRep (Proxy :: Proxy (Hostname, Maybe LanguageCode)))
      subserver = addCapture server $ \pathSegment -> withRequest $ \req -> 
        case DL.lookup (fromString "Host") (requestHeaders req) of
          Nothing -> 
            delayedFail err406
          Just hname -> 
            if Prelude.not (isWhiteListedDomain hname)
              then delayedFail err406
              else if pathSegment `DL.elem` knownLanguageCodes
                then pure $ (toS hname, Just $ LanguageCode pathSegment)
                else pure $ (toS hname, Nothing)

isWhiteListedDomain :: C8.ByteString -> Bool
isWhiteListedDomain = undefined 
    
knownLanguageCodes :: [Text]
knownLanguageCodes = undefined
@fisx
Copy link
Member

fisx commented Dec 1, 2024

I don't understand. CaptureHint is exported from Servant.Server.Internal.Router, and internal modules are exposed in the cabal file. did you look in the right place? (did i...?)

@tchoutri
Copy link
Contributor

tchoutri commented Dec 1, 2024

@fisx I believe Saurabh is asking "why is this not part of the external API" (which would be presumed to be stable, or at least officially endorsed).

@fisx
Copy link
Member

fisx commented Dec 1, 2024

i see, that makes sense. i'm not sure, then. as an application developer i'm really bad at library interface hygene and would probably just import the internal module. :)

@tchoutri
Copy link
Contributor

tchoutri commented Dec 1, 2024

@saurabhnanda Could you please use this module and tell us if the constructs in it are mature enough? If they are, they I guess we can move them to an external module. Even making a guide for your usecase could be a fantastic way to help out the next person who needs i18n. :)

@saurabhnanda
Copy link
Author

@tchoutri @fisx my bad. CaptureHint is indeed exported. I was on an older version of servant in this particular project and didn't realize it.

Now, even though I have access to CaptureRouter, addCapture and CaptureHint, my solution is not working. It expects the language fragment to always be present. It cannot capture optionally. I've updated the code snippet above (in the original post).

@saurabhnanda saurabhnanda changed the title Any reason why CaptureHint is not exported? How to capture a path segment optionally? (was: Any reason why CaptureHint is not exported?) Dec 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants