diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 3.0.3
+
+* Add `runHostPortFullUrl` to allow launching arbitrary URLs [#2](https://github.com/yesodweb/wai-handlers/pull/2)
+
 ## 3.0.2.4
 
 * Drop dependency on blaze-builder, requiring streaming-commons >= 0.2
diff --git a/Network/Wai/Handler/Launch.hs b/Network/Wai/Handler/Launch.hs
--- a/Network/Wai/Handler/Launch.hs
+++ b/Network/Wai/Handler/Launch.hs
@@ -6,6 +6,7 @@
     , runUrl
     , runUrlPort
     , runHostPortUrl
+    , runHostPortFullUrl
     ) where
 
 import Network.Wai
@@ -165,21 +166,21 @@
 
 #if WINDOWS
 foreign import ccall "launch"
-    launch' :: Int -> CString -> IO ()
+    launch' :: CString -> IO ()
 #endif
 
-launch :: Int -> String -> IO ()
+launch :: String -> IO ()
 
 #if WINDOWS
-launch port s = withCString s $ launch' port
+launch url = withCString url $ launch' url
 #else
-launch port s = forkIO (rawSystem
+launch url = forkIO (rawSystem
 #if MAC
     "open"
 #else
     "xdg-open"
 #endif
-    ["http://127.0.0.1:" ++ show port ++ "/" ++ s] >> return ()) >> return ()
+    [url] >> return ()) >> return ()
 #endif
 
 run :: Application -> IO ()
@@ -195,7 +196,13 @@
 --
 -- @since 3.0.1
 runHostPortUrl :: String -> Int -> String -> Application -> IO ()
-runHostPortUrl host port url app = do
+runHostPortUrl host port url app = runHostPortFullUrl host port ("http://127.0.0.1:" ++ show port ++ "/" ++ url) app
+
+-- | Generic version of runHostPortUrl that allows arbitrary URLs to launch
+--
+-- @since 3.0.2.5
+runHostPortFullUrl :: String -> Int -> String -> Application -> IO ()
+runHostPortFullUrl host port url app = do
     ready <- newEmptyMVar
     active <- newIORef True
     let settings =
@@ -210,7 +217,7 @@
       -- serve app, keep updating the activity flag
       (Warp.runSettings settings (ping active app))
       -- wait for server startup, launch browser, poll until server idle
-      (takeMVar ready >> launch port url >> loop active)
+      (takeMVar ready >> launch url >> loop active)
 
 loop :: IORef Bool -> IO ()
 loop active = do
diff --git a/wai-handler-launch.cabal b/wai-handler-launch.cabal
--- a/wai-handler-launch.cabal
+++ b/wai-handler-launch.cabal
@@ -1,5 +1,5 @@
 Name:                wai-handler-launch
-Version:             3.0.2.4
+Version:             3.0.3
 Synopsis:            Launch a web app in the default browser.
 description:         API docs and the README are available at <http://www.stackage.org/package/wai-handler-launch>.
 License:             MIT
@@ -15,7 +15,7 @@
     Exposed-modules: Network.Wai.Handler.Launch
     build-depends:   base                    >= 4       && < 5
                    , wai                     >= 3.0     && < 3.3
-                   , warp                    >= 3.0     && < 3.3
+                   , warp                    >= 3.0     && < 3.4
                    , http-types              >= 0.7
                    , transformers            >= 0.2.2
                    , bytestring              >= 0.10.4
@@ -33,4 +33,4 @@
 
 source-repository head
   type:     git
-  location: git://github.com/yesodweb/wai.git
+  location: git://github.com/yesodweb/wai-handlers.git
diff --git a/windows.c b/windows.c
--- a/windows.c
+++ b/windows.c
@@ -2,11 +2,7 @@
 #include <shellapi.h>
 #include <stdio.h>
 
-void launch(int port, char *s)
+void launch(char *s)
 {
-    int len = 8 + strlen("http://127.0.0.1:") + strlen(s);
-    char *buff = malloc(len);
-    _snprintf(buff, len, "http://127.0.0.1:%d/%s", port, s);
-    ShellExecute(NULL, "open", buff, NULL, NULL, SW_SHOWNORMAL);
-    free(buff);
+    ShellExecute(NULL, "open", s, NULL, NULL, SW_SHOWNORMAL);
 }
