Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Azure Functions in Swift! Purely in Swift!

License

NotificationsYou must be signed in to change notification settings

SalehAlbuga/azure-functions-swift

Repository files navigation

vercliverSwift Package Manager compatibledocs-statusSwift versionLicense: MIT

Chat

WriteAzure FunctionsinSwift.

This framework supports the new Azure FunctionsCustom Handlers (starting from 0.6.0) in addition to the traditional custom worker.

Disclaimer: This is a community open source project, not an official Azure project

Deploy a sample project to Azure!

Classic worker sample:

Deploy to Azure

Custom Handler sample:

Deploy to Azure

Examples

A Timer Function (Custom Handler):

import Foundationimport AzureFunctionsimport VaporclassTimerFunction:Function{requiredinit(){        super.init()self.name="TimerFunction"self.functionJsonBindings=[["type":"timerTrigger","name":"myTimer","direction":"in","schedule":"*/5 * * * * *"]]        //or        //self.trigger = TimerTrigger(name: "myTimer", schedule: "*/5 * * * * *")        app.post([PathComponent(stringLiteral: name)], use:run(req:))}func run(req:Request)->InvocationResponse{varres=InvocationResponse()        res.appendLog("Its is time!")return res}}

An HTTP Function (Classic Worker):

import Foundationimport AzureFunctionsclassHttpFunction:Function{requiredinit(){        super.init()self.name="HttpFunction"self.trigger=HttpRequest(name:"req")}overridefunc exec(request:HttpRequest, context:inoutContext, callback:@escapingcallback)throws{letres=HttpResponse()varname:String?iflet data= request.body,let bodyObj:[String:Any]=try?JSONSerialization.jsonObject(with: data, options:[])as?[String:Any]{            name=bodyObj["name"]as?String}else{            name= request.query["name"]}        res.body="Hello\(name??"buddy")!".data(using:.utf8)returncallback(res);}}

Getting Started

Installation and Requirements

Swift 5.2 or later or Xcode 11 or later on macOS

Swift installation:https://swift.org/getting-started/#installing-swift

Azure Functions Core Tools

Install the latestAzure Functions Core Tools.

Swift Functions Tools

Just like Core Tools, Swift Functions Tools make Swift functions development easier and much more convenient.

OnmacOS, you can install it fromHomebrew 🍺

brew install salehalbuga/formulae/swift-func

onLinux,

Clone the repo the tools repo

git clone https://github.com/SalehAlbuga/azure-functions-swift-tools

Install

make install

It installs a CLI tool calledswiftfunc that can be used to create projects, functions and run them locally.

Creating a new Project/Azure Functions app

Run the init command to create a new Azure Functions application:

swiftfunc init myApp [-hw]

It will create a new app in a new folder, and a folder namedfunctions inside the Sources target where Functions should be (/myApp/Sources/myApp/functions).The project created is a Swift package project with the Azure Functions framework dependency.

Pass-hw or--http-worker option to create the project with theCustom Handler template.

Creating a simple HTTP function

Inside the new directory of your project, run the following to create a new HTTP Function namedhello:

swiftfunc new http -n hello [-hw]

The new function file will be created in the following pathSources/myApp/functions/hello.swift.

Similar to theinit command, pass-hw or--http-worker option to create the new function with the Custom Handler template.

Running the new Functions App

Runswiftfunc run in the project directory to run your Swift Functions project locally. It will compile the code and start the host for you(as if you were runningfunc host start). The host output should show you the URL ofhello function created above. Click on it to run the function and see output!

Deploying to Azure ☁️

There are 2 methods to deploy Swift Functions to Azure

Container Functions

To deploy the Function App in a Container, you can either use the Functions Core Toolfunc deploy command, where it will build the image, push it to a registry and set it in the destination Function App or you can do that manually as shown below.

Build the image (Dockerfile is provided when the project is created)

docker build -t<imageTag>.

If you're using DockerHub then the tag would beusername/imageName:version.If you're using ACR (Azure Container Registry) or any other private registry the tag would beregistryURL/imageName:version

Then push it

docker push<imageTag>

InAzure portal, create a new Function App withDocker Container as the Publish option. Under Hosting options make sure Linux is selected as OS.

Once the app is created or in any existing Container Function App, underPlatform Features, selectContainer settings and set the registry and select image you pushed.

You can use the buttons below to deploy prebuilt sample project to your Azure subscription

Deploy to Azure

Custom Handler sample:

Deploy to Azure

Hosting on a Linux Consumption Plan

First, you need to set the following App Setting in the Function App on Azure.LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/site/wwwroot/workers/swift/lib/

Then depending if you're developing on a Linux machine or a Mac:

Linux

Login to your Azure account from Azure CLI

az login

When Azure CLI finishes loading your subscription(s) info, run:

swiftfunc publish myswiftfunctions

Swift Function Tools publish command is going to compile, export and publish your Swift Functions project.

macOS

Publishing to a Function App in a Linux Consumption Plan from macOS requires the app to be build in a Linux container first, to do that you can use VSCode Dev Containers.The project needs to be created with the-dc or--dev-container option to have the Swift Function Dev Container added (or you can create a new one and copy the .devcontainer folder to your project).swiftfunc init myFunctionApp -hw -dc

Reopen the folder in dev container (Command-Shift-P, search for and selectRemote-Containers: Reopen in Container)

Once the dev container is ready, follow the same Linux steps above to publish the app!

Bindings

Azure Functions offer a variety ofBindings and Triggers

The trigger, input bindings and output bindings of a Function are set in its initializer. Azure Functions in Swift must subclass theFunction class from the framework.

Custom Handler (HTTP Worker)

When using the Custom Handler mode you can use all Azure Functions bindings and triggers by setting thefunctionJsonBindings property to the JSON config of the bindings/triggers in Azure Functionsdocs. You can also use the framework supported Trigger/Binding types listed below.

Traditional Worker (Classic)

Currently the following are supported by this mode. More bindings will be implemented and many improvements will be made in the future.

Swift TypeAzure Functions BindingDirection
HttpRequestHTTP Triggerin
HttpResponseOutput HTTP Responseout
TimerTriggerTimer Triggerin
Message datatypeString (binding defined by Table in constructor)Input and Ouput Tablein, out
Message datatypeString (binding defined by Queue in constructor)Output Queue Messageout
Message datatypeString (binding defined by Queue in constructor)Queue Triggerin
Blob (the blob data prob is either String or Data)Input Blobin
String or DataOutput Blobout
BlobBlob Triggerin
ServiceBusMessageService Bus Output Messageout
ServiceBusMessageService Bus Triggerin

Custom Handler (HTTP Worker)

import AzureFunctionsimport Vaporclass QueueFunction:Function{requiredinit(){        super.init()self.name="QueueFunction"self.functionJsonBindings=[["connection":"AzureWebJobsStorage","type":"queueTrigger","name":"myQueueTrigger","queueName":"myqueue","direction":"in"]]        // or        //self.trigger = Queue(name: "myQueueTrigger", queueName: "myqueue", connection: "AzureWebJobsStorage")                app.post([PathComponent(stringLiteral: name)], use:run(req:))}func run(req:Request)->InvocationResponse{...

Traditional Worker (Classic)

import AzureFunctionsclass HttpFunction:Function{requiredinit(){        super.init()self.name="HttpFunction"self.trigger=HttpRequest(name:"req")self.inputBindings=[Blob(name:"fileInput", path:"container/myBlob.json", connection:"AzureWebJobsStorage")]self.outputBindings=[Queue(name:"queueOutput", queueName:"myQueue", connection:"AzureWebJobsStorage")]}overridefunc exec(request:HttpRequest, context:inoutContext, callback:@escapingcallback)throws{...

Writing Swift Functions

Traditional Worker (Classic)

Based on your Function's trigger type the worker will call the appropriateexec overload. For instance, if the Function is timer-triggered, then the worker will call

exec(timer:context:callback:)

If it was an HTTP-triggered one:

exec(request:context:callback:)

You can see the list of available overloads in Xcode.

Input and Output bindings are available in the context as Dictionaries, where you can access/set the values using the binding names specified in the constructor.For example:

lettableVal= context.inputBindings["myTableInput"]
context.outputBindings["myQueueOutput"]="new item!"

Custom Handler (HTTP Worker)

The framework uses Vapor 4.0 HTTP server. TheFunction class has theapp property, thats the Vapor app instance you can use to register your functions's HTTP route.

class myFunction:Function{requiredinit(){        super.init()self.name="myFunction"self.functionJsonBindings=[["connection":"AzureWebJobsStorage","type":"queueTrigger","name":"myQueueTrigger","queueName":"myqueue","direction":"in"]]                app.post([PathComponent(stringLiteral: name)], use:run(req:))}func run(req:Request)->InvocationResponse{varres=InvocationResponse()        iflet payload=try? req.content.decode(InvocationRequest.self){            res.appendLog("Got\\(payload.Data?["myQueueTrigger"]??"")")        }        return res    }}

The framework also provides the function invocation Request and Response models needed for Azure Function host, which conform to Content protocol from Vapor, along with helper methods.

Invocation Request:

/// Trigger/Bindings data (values).vardata:[String:AnyCodable]?/// Trigger/Bindings metadata.varmetadata:[String:AnyCodable]?

Invocation Request:

/// Output bindings values dictionaryvaroutputs:[String:AnyCodable]?/// Functions logs array. These will be logged when the Function is executedvarlogs:[String]=[]/// The $return binding valuevarreturnValue:AnyCodable?

Framework Updates

As the framework is being actively updated, update the framework and the tools if you're having any issues or want to have the latest features and improvements.

To update the framework:

swift package update

To update the tools onmacOS

brew upgrade salehalbuga/formulae/swift-func

onLinux

git clone https://github.com/SalehAlbuga/azure-functions-swift-toolsmake install

Storage Connections and other settings

In the generatedmain.swift you can define your debugAzureWebJobsStorage and optionally any other connections/environment vars.Additionally, you can change the default Extension Bundle id and version.

////  main.swift//  ////  Auto Generated by SwiftFunctionsSDK////  Only set env vars or register/remove Functions. Do Not modify/add other code//import AzureFunctionsletregistry=FunctionRegistry()registry.AzureWebJobsStorage="yourConnection" //Remove before deploying. Do not commit or push any Storage Account keysregistry.EnvironmentVariables=["queueStorageConnection":"otherConnection"]// Optionally you can change the default ExtensionBundleId and version registry.ExtensionBundleId="Microsoft.Azure.Functions.ExtensionBundle"registry.ExtensionBundleVersion="[1.*, 2.0.0)"registry.register(hello.self)...

Be sure not to commit any debugging Storage Account keys to a repo

Logging

Traditional Worker (Classic)

You can log using the log method incontext object

context.log(_)

Custom Handler (HTTP Worker)

Logs are returned in the InvocationResponse obj. You can append logs:

res.appendLog(_)

Code Execution Note

Traditional Worker (Classic)

When your Function is done executing the logic you should call the provided callback passing the$return output binding value or withtrue if none.

callback(res)

About

Azure Functions in Swift! Purely in Swift!

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp