packages feed

gopher-proxy 0.1.0.2 → 0.1.1.0

raw patch · 5 files changed

+82/−28 lines, 5 files

Files

ChangeLog.md view
@@ -1,5 +1,15 @@ # Revision history for gopher-proxy +## 0.1.1.0 -- 2017-01-06++* Add two options: `--title` and `--server-name`+* Fix the README on hackage+* Elaborate the package description++## 0.1.0.2  -- 2017-01-05++* Fixed a build issue+ ## 0.1.0.1  -- 2017-01-04  * Updated package metadata
README.md view
@@ -8,26 +8,25 @@      gopher-proxy --host foo.org --http-port 8080 -In this particular example, gopher-proxy would proxy the foo.org gopher server and bind its http service on `127.0.0.1:8080` (to be proxied to by another web server like `nginx`).+In this particular example, gopher-proxy would proxy the `foo.org` gopher server and bind its http service on `127.0.0.1:8080` (to be proxied to by another web server like `nginx`). -There are these additional flags which allow tweaking of exact behavior as well:+These are all optional flags which allow to change default behavior: -option                | meaning-----------------------|---------------------------------------------------------------------------------------------------------`--port`              | The port of the gopher server, defaults to `70`-`--css-url`           | Use some specific css file instead of the default one.-`--css-url`           | The http path of the css file, defaults to `/gopher-proxy.css` (should be changed, if your gopher server has a file with the same name-`--base-url`          | The path of the directory which will appear as root directory of gopher-proxy to the user, defaults to `/`. Should be changed if you configured your proxying web server to expose gopher-proxy as, say `/gopher-space/`.-`--listen-public`     | If this flag is set, gopher-proxy will accept connections on its public IP address(es).-`--default-mime-type` | Mime type to use if spacecookie can't guess it, defaults to "application/octet-stream"-`--timeout`           | Timeout when connecting in milliseconds, defaults to 10 seconds.+* `--port`: The port of the gopher server, defaults to `70`+* `--css-url`: Use some specific css file instead of the default one.+* `--css-url`: The http path of the css file, defaults to `/gopher-proxy.css` (should be changed, if your gopher server has a file with the same name+* `--base-url`: The path of the directory which will appear as root directory of gopher-proxy to the user, defaults to `/`. Should be changed if you configured your proxying web server to expose gopher-proxy as, say `/gopher-space/`.+* `--listen-public`: If this flag is set, gopher-proxy will accept connections on its public IP address(es).+* `--default-mime-type`: Mime type to use if spacecookie can't guess it, defaults to "application/octet-stream"+* `--timeout`: connection timeout in milliseconds, defaults to 10 seconds.+* `--server-name`: The server name of the server to proxy, defaults to the host name. This value is used to detect wether a menu item is pointing to another gopher server than the proxied one. This is particularly useful, if you use e. g. `127.0.0.1` instead of the public host name.  ## Things to keep in mind -* Your gopher server must send UTF-8-encoded gopher menus+* Your gopher server must send UTF-8-encoded gopher responses * gopher-proxy might misinterpret certain content, because of the context-sensitive nature of gopher * gopher-proxy does not support Gopher+  ## Roadmap -[ ] Add Logging+- [ ] Add Logging
gopher-proxy.cabal view
@@ -2,9 +2,30 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                gopher-proxy-version:             0.1.0.2+version:             0.1.1.0 synopsis:            proxy gopher over http-description:         A simple gopher-over-http proxy to http-ify gopher spaces.+description:+  @gopher-proxy@ allows to proxy gopher over HTTP, which is mainly useful for HTTP-ifying a specific gopher space.+  .+  A simple invocation looks like this:+  .+  @+  gopher-proxy --host example.org --http-port 8080+  @+  .++  In this particular example @gopher-proxy@ does the following things:+  .+  * Takes HTTP requests on @127.0.0.1:8080@ (to be used by a proxying web server, like nginx), converts those to gopher requests to @example.org@ and returns the gopher responses as HTTP responses+  .+  * Links menu items pointing to external servers to @gopher://@ URLs (this ensures that only one gopher server is proxied) and recognizes <https://en.wikipedia.org/wiki/Gopher_(protocol)#URL_links URL links> which are converted to normal HTML links+  .+  * Tries to guess the correct mime-type for every gopher-served file (as it is not included in the response) and wraps text files in a HTML container.+  .+  * And generally works hard to offer the best HTTP equivalent of a given gopher space :)+  .+  To learn about the other parameters for tweaking the behavior of @gopher-proxy@ <#readme see the readme>.+ license:             GPL-3 license-file:        LICENSE author:              sternenseemann
src/GopherProxy/Params.hs view
@@ -9,7 +9,8 @@ import qualified Data.ByteString as BS import Data.Maybe (fromMaybe) import Data.Monoid ((<>))-import Data.Text (Text ())+import Data.Text (Text (), pack)+import Data.Text.Encoding import Network.Mime (MimeType (), defaultMimeType) import Network.Socket (HostName (), PortNumber ()) import Options.Applicative@@ -25,6 +26,8 @@     , listenPublic :: Bool     , defaultMime  :: MimeType     , timeoutms    :: Int+    , serverName   :: Maybe HostName+    , title        :: String     }  helpfulParams :: ParserInfo Params@@ -48,7 +51,7 @@     (long "css-path"     <> metavar "PATH"     <> help "path of the css to be used"))-  <*> optionalWithDefault "/gopher-proxy.css" (option auto+  <*> optionalWithDefault "/gopher-proxy.css" (option utf8ByteString     (long "css-url"     <> metavar "PATH"     <> help "absolute location of the css on the web server, defaults to \"/gopher-proxy.css\""))@@ -67,7 +70,18 @@     (long "timeout"     <> metavar "MILLISECONDS"     <> help "timeout for connecting to the specified gopher server, defaults to 10s."))+  <*> optional (strOption+    (long "server-name"+    <> metavar "HOSTNAME"+    <> help "The server name of the target gopher server, it sends in gopher menus. Defaults to hostname."))+  <*> optionalWithDefault "gopher-proxy" (strOption+    (long "title"+    <> metavar "STRING"+    <> help "title of the resulting html page")) ++utf8ByteString :: ReadM BS.ByteString+utf8ByteString = encodeUtf8 . pack <$> str  optionalWithDefault :: a -> Parser a -> Parser a optionalWithDefault def p = fromMaybe def <$> optional p
src/Main.hs view
@@ -64,8 +64,9 @@  gopherResponse :: Params -> Application gopherResponse cfg r respond = do+  let req = rawPathInfo r   (resp, mime) <- (flip fmap)-    (makeGopherRequest cfg (B.fromStrict (rawPathInfo r))) $+    (makeGopherRequest cfg (B.fromStrict req)) $      \case        Just r  -> r        Nothing -> ( MenuResponse [ MenuItem '3' "An error occured while retrieving server's response." "" "" 0 ]@@ -80,11 +81,11 @@   respond $ uncurry (responseLBS status) $     case resp of       MenuResponse _ ->-        ([("Content-type", "text/html")], renderBS (gResponseToHtml cfg resp))+        ([("Content-type", "text/html")], renderBS (gResponseToHtml cfg req resp))       FileResponse b ->         case mimeTuple mime of           ("text", "html") -> ([("Content-type", mime)], b)-          ("text", _)      -> ([("Content-type", "text/html")], renderBS (gResponseToHtml cfg resp))+          ("text", _)      -> ([("Content-type", "text/html")], renderBS (gResponseToHtml cfg req resp))           _                -> ([("Content-type", mime)], b)  mimeTuple :: MimeType -> (BS.ByteString, BS.ByteString)@@ -132,16 +133,17 @@   | T.last base == '/' = base <> path   | otherwise = base <> "/" <> path --- we generally assume that everything is utf-8 encoded-gResponseToHtml :: Params -> GopherResponse -> Html ()-gResponseToHtml cfg res+gResponseToHtml :: Params -> BS.ByteString -> GopherResponse -> Html ()+gResponseToHtml cfg req res   = doctype_ <> html_       (head_ (meta_ [charset_ "utf-8"]              <> meta_ [term "viewport" "width=device-width"]-             <> title_ "gopher-proxy"-             <> link_ [rel_ "stylesheet", type_ "text/css", href_ . decodeUtf8 . cssUrl $ cfg])+             <> title_ title'+             <> link_ [rel_ "stylesheet", type_ "text/css", href_ cssUrl'])       <> body_ bodyContent)-  where bodyContent = case res of+  where cssUrl' = decodeUtf8 . cssUrl $ cfg+        title' = (toHtml (title cfg)) <> (toHtml (" – " :: Text)) <> (toHtml req)+        bodyContent = case res of                         FileResponse bytes -> pre_ (toHtml bytes)                         MenuResponse items -> ul_ $ foldl (itemChain cfg) mempty items @@ -153,11 +155,19 @@                        'i' -> toHtml desc                        '3' -> span_ [class_ "error"] (toHtml desc)                        _   -> a_ [href_ url] (toHtml desc)+          serverName' = case serverName cfg of+                          Just s -> s+                          Nothing -> hostname cfg           url = if "URL:" `T.isPrefixOf` path                   then T.drop 4 path-                  else if host' == hostname cfg && port' == port cfg+                  else if host' == serverName' && port' == port cfg                     then prependBaseUrl (baseUrl cfg) path-                    else prependBaseUrl ("gopher://" <> (T.pack host') <> ":" <> (T.pack (show port'))) path+                    else gopherUrl host' port' typec path++gopherUrl :: HostName -> PortNumber -> Char -> Text -> Text+gopherUrl host port typeChar path = prependBaseUrl+  ("gopher://" <> (T.pack host) <> ":" <> (T.pack (show port)) <> "/" <> (T.singleton typeChar) <> "/")+  path  main :: IO () main = do