Azure Functions with Go and SharePoint integration
Just found out I didn't published an article about using Go with Azure Functions and SharePoint integration. So here it is.
Why Serverless?
Serverless is a paradigm of computing. It's a way of building and running applications and services without thinking about servers. It's a way of building applications where you don't have to worry about managing infrastructure, scaling, high availability, etc.
Azure Functions is a serverless compute service that lets you run code on-demand without having to explicitly provision or manage core infrastructure. Azure Functions can scale based on demand and you pay only for the time your code runs and the resources you consume.
It's very handy for the cases when you need a backend service of job with a relatively small or unpredictable consumption.
Why Go?
Support for custom handlers in Azure Functions is a great feature. It allows to use any language or framework to build a custom handler. Go is a great choice for a number of reasons: it's a...
Why SharePoint?
In a majority of enterprise projects with Microsoft 365; SharePoint is a platform which is already there, you can use it for business data or document management. Nice to have option for a flavor of collaborative scenarios.
What's in the box?
Let's combine this together: Azure Functions + Go + SharePoint. Sounds like a good idea, right? Yep, but could be tricky to start with as it's a bit unusual combination. I've created a sample project to help you get started.
Code source: https://github.com/koltyakov/az-fun-go-sp
Prerequisites
Mac or Linux machine, or Windows WSL2 are preferred.
All the commands within the sample assumed running in `bash`.
Create Azure Function Resource
This flow is dev friendly when it comes to quick experiments. For production deployments please consider infrastructure as code and automation via DevOps.
In VS Code with Azure Functions extension installed:
Don't forget to remove the resource group after experiments to avoid any unexpected charges. Yet, with Serverless you mostly can expect almost zero paycheck if it's not used.
Project structure highlights
`.vscode/` - VSCode settings folder, mostly standard, however, `settings.json` has important modification `"azureFunctions.deploySubpath": "./functions"` which changes root folder for functions deployment via `ms-azuretools` extension
`functions/` - everything related to Azure Functions, isolation makes things simpler while no mixing with custom handler related project files
- Functions folders, containing `function.json` file
- `.funcignore` - functions ignore file with handy ignore options
- `host.json` - host configuration file, mostly standard, interesting and important section is `customHandler`, especially `"enableForwardingHttpRequest": true` which is not added by default
- `local.settings[.sample].json` - contains configuration which is needed for local development and debug, local settings should be excluded from Git to avoid secrets leak
- `proxies.json` - bypassing endpoints to external resources
`handlers/` - Handlers sub package grouping by extensible handlers methods
`debug.go` - grabs Azure Functions settings to use when starting the handlers' server separately, is not included into production build
`main.go` - Custom Handler Go server entry point
`mux.go` - routes and handler binding configuration
`sp.go` - SharePoint Client and authentication constructor
`Makefile` - useful tasks/commands collection for project automation
Local start/debug
Copy/rename `local.settings.sample.json` to `local.settings.json`.
Provide authentication parameters:
Add-in Only auth is used as a sample.
Start the local server with `make start`
Navigate to one of the URL endpoints printed in the console
Debugging Go code
For breaking points debugging in VSCode a number of approaches can be used: attaching to process or connecting to server. In most cases, one would prefer restarting Go server without stoping and restarting `func start` session. Also, it's simpler to place a breakpoint, switch to `main.go` file, and launch debug. Such a scenario can be covered with:
领英推荐
make debug
The local function app is started without actually starting the Go side-car server, but mimicking the process for functions core utility.
Then, the Go application can be started or restarted as many times as needed, e.g. using `go run ./` or launch debug UI.
Build and deploy
1. Run build command:
make build-prod
The assumption is that a Linux plan was selected for the function app.
The build creates `bin/server` binary with the Go custom handler.
2. In VSCode,
Publish via CLI
Publishing via CLI is a faster and more robust scalable way.
make appname="functionapp_name" publish
where `"functionapp_name"` is the name of your Function App instance.
`az` CLI is required.
Configure environment variables
In the Azure Function app, create and provide the following environment variables:
Depending on the SharePoint environment and use case, auth strategy can be different. For a production installation Azure Certificate Auth might be preferred.
`sp.go/getSP` handler should be aligned with authentication parameters.
Overriding host's settings
Azure Functions use .Net native approaches dealing with settings. Hierarchical settings can be overriden with environment variables.
E.g., you need `server.exe` locally but a Linux Functions host still needs `server` (without extention) in `hosts.json`, it can be redefined in `local.settings.json` with a value:
{
// ...
"Values": {
// ...
"AzureFunctionsJobHost__customHandler__description__defaultExecutablePath": "bin/server.exe"
}
}
Adding new function
1. `CMD+Shift+P` type `Azure Functions: Create Function...`
2. Select a template for your function, e.g. `HTTP trigger`
3. Provide a function name. e.g. `HttpTrigger1`
4. Select authorization level, e.g. `Function`
A function's folder and bindings definition is created `functions/HttpTrigger1/function.json`:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["get", "post"]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
5. Run `make start` and follow via `https://localhost:7071/api/HttpTrigger1` for just created function's binding
The Echo service handler will response with URL path `/api/HttpTrigger1`, that's because created function is not processed with specific route Go custom handler yet.
`Ctrl+C` to stop running functions host.
6. Create `handlers/HttpTrigger1.go` and paste:
package handler
import (
"fmt"
"net/http"
)
// HTTPTrigger1 handles a function's logic
func (h *Handlers) HTTPTrigger1(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
fmt.Fprintf(w, "Hello, %s!", name)
}
7. Bind a handler with a route in `mux.go` in API routes section:
http.HandleFunc("/api/HttpTrigger1", h.HTTPTrigger1)
8. Run `make start` and navigate to `https://localhost:7071/api/HttpTrigger1?name=Function`
`Hello, Function!` should be responded back.
SharePoint API in Go
Check `handlers/fields.go` and `handlers/lists.go` as samples of comuting with SharePoint instance.
In a handler, `h.sp.` exposes access to SharePoint object model.
The API layer is powered by gosip.
Reference
Solutions Architect, Microsoft MVP
2 年On Friday there will be the part two with Infrastructure as Code with #terraform diving in.