Running Go Web Apps on IIS with HttpPlatformHandler
A post about how to create a simple Go web app and host it on IIS with HttpPlatformHandler
HttpPlatformHandler can help IIS host Java/Python/Node.js/Go applications, so in this post we wil see how to configure a Go/Echo web app on IIS and troubleshoot the common issue.
Prerequisites
To follow this post, you need to have the following software installed,
- Windows 10 or Windows Server 2016 or later (IIS 10 or later)
- HttpPlatformHandler v1.2 (from Microsoft) or v2.0 (from LeXtudio)
Basic Go/Echo Setup
At the beginning, we will start by installing Go on this machine,
1
winget install GoLang.Go
After that we will start to make a sample application,
1
2
3
4
5
cd C:\
mkdir test-go
cd test-go
go mod init test-go
go get github.com/labstack/echo/v4
Next, create a file server.go
with the following content,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":1323"))
}
The steps are taken from Echo documentation.
Now on this Windows machine with Go and Echo installed, a simple command go run server.go
in the directory of C:\test-go\
can launch the application at port 1323.
1
2
3
4
5
6
7
8
9
10
11
PS C:\test-go> go run server.go
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.11.4
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
⇨ http server started on [::]:1323
To make this Go web app works with IIS, we need to modify the code a bit to read the port number from environment variable HTTP_PLATFORM_PORT
,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main
import (
"flag"
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
port := flag.String("port", "1323", "port to listen on")
flag.Parse()
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":" + *port))
}
Compile the code to an executable file,
1
go build server.go
After compilation, a file server.exe
is created in the directory.
HttpPlatformHandler Setup
Now let’s download and install HttpPlatformHandler on IIS, and add a web.config
in C:\test-go
,
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" requireAccess="Script" />
</handlers>
<httpPlatform stdoutLogEnabled="true" stdoutLogFile=".\go.log" startupTimeLimit="20" processPath="server.exe" arguments="--port %HTTP_PLATFORM_PORT%">
</httpPlatform>
</system.webServer>
</configuration>
With all settings in place, I can go back to IIS Manager and create a site (I chose *:8086 as site binding) to point to C:\flask-test
. By opening a web browser and navigate to http://localhost:8086/
, I should now see “Hello, World!”. Ah, what happened?
Troubleshooting
0x8007005
Yeah I am not able to see “Hello, World!” but a Bad Gateway error page with the Error Code of 0x80070005
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
> .\Err.exe 80070005
# No results found for hex 0x4c5c575 / decimal 80070005
# for hex 0x80070005 / decimal -2147024891
COR_E_UNAUTHORIZEDACCESS corerror.h
# Access is denied.
DIERR_OTHERAPPHASPRIO dinput.h
DIERR_READONLY dinput.h
DIERR_HANDLEEXISTS dinput.h
DSERR_ACCESSDENIED dsound.h
STIERR_READONLY stierr.h
STIERR_NOTINITIALIZED stierr.h
E_ACCESSDENIED winerror.h
# General access denied error
# as an HRESULT: Severity: FAILURE (1), FACILITY_WIN32 (0x7), Code 0x5
# for hex 0x5 / decimal 5
ERROR_ACCESS_DENIED winerror.h
# Access is denied.
# 9 matches found for "80070005"
This isn’t hard to understand, because anything under C:\test-go\
is protected and not accessible by IIS application pools by default. So I need to grant read permission to the local group IIS_IUSRS
.
0x8007002
After fixing the file system permission issue, another Bad Gateway error page with the Error Code of 0x80070002
appears.
The cause is actually simple, that Windows/IIS tries to resolve server.exe
from the system path, but it is not there. So I need to modify web.config
to use the full path or simply .\server.exe
to make it work.
Side Notes
So, at this very moment, the web.config
should look like this,
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" requireAccess="Script" />
</handlers>
<httpPlatform stdoutLogEnabled="true" stdoutLogFile=".\go.log" startupTimeLimit="20" processPath=".\server.exe" arguments="--port %HTTP_PLATFORM_PORT%">
</httpPlatform>
</system.webServer>
</configuration>
Go on IIS Express
You can take a look at the new open source HttpPlatformHandler v2.0 from LeXtudio.
Other Languages on IIS?
If you want to learn more about HttpPlatformHandler and how to host other languages (Python/Node.js/Java), you can read this post.