ASP.NET Core가 있는 OWIN(Open Web Interface for .NET)Open Web Interface for .NET (OWIN) with ASP.NET Core

작성자: Steve SmithRick AndersonBy Steve Smith and Rick Anderson

ASP.NET Core는 OWIN(Open Web Interface for .NET)을 지원합니다.ASP.NET Core supports the Open Web Interface for .NET (OWIN). OWIN을 사용하면 웹 앱을 웹 서버에서 분리할 수 있습니다.OWIN allows web apps to be decoupled from web servers. 미들웨어를 파이프라인에서 사용하고 요청 및 관련된 응답을 처리하기 위한 표준 방법을 정의합니다.It defines a standard way for middleware to be used in a pipeline to handle requests and associated responses. ASP.NET Core 응용 프로그램 및 미들웨어는 OWIN 기반 응용 프로그램, 서버 및 미들웨어와 상호 운용할 수 있습니다.ASP.NET Core applications and middleware can interoperate with OWIN-based applications, servers, and middleware.

OWIN은 서로 다른 개체 모델이 있는 두 프레임워크를 함께 사용할 수 있도록 허용하는 분리 계층을 제공합니다.OWIN provides a decoupling layer that allows two frameworks with disparate object models to be used together. Microsoft.AspNetCore.Owin 패키지는 두 개의 어댑터 구현을 제공합니다.The Microsoft.AspNetCore.Owin package provides two adapter implementations:

  • ASP.NET Core에서 OWIN으로ASP.NET Core to OWIN
  • OWIN에서 ASP.NET Core로OWIN to ASP.NET Core

이렇게 하면 ASP.NET Core를 OWIN 호환 가능한 서버/호스트를 기반으로 호스팅하거나 다른 OWIN 호환 가능한 구성 요소를 ASP.NET Core를 기반으로 실행되도록 할 수 있습니다.This allows ASP.NET Core to be hosted on top of an OWIN compatible server/host or for other OWIN compatible components to be run on top of ASP.NET Core.

참고

이러한 어댑터를 사용하면 성능 비용이 수반됩니다.Using these adapters comes with a performance cost. ASP.NET Core 구성 요소만을 사용하는 앱은 Microsoft.AspNetCore.Owin 패키지 또는 어댑터를 사용하면 안 됩니다.Apps using only ASP.NET Core components shouldn't use the Microsoft.AspNetCore.Owin package or adapters.

예제 코드 살펴보기 및 다운로드(다운로드 방법)View or download sample code (how to download)

ASP.NET 파이프라인에서 OWIN 미들웨어 실행Running OWIN middleware in the ASP.NET pipeline

ASP.NET Core의 OWIN 지원은 Microsoft.AspNetCore.Owin 패키지의 일부로 배포됩니다.ASP.NET Core's OWIN support is deployed as part of the Microsoft.AspNetCore.Owin package. 이 패키지를 설치하여 OWIN 지원을 프로젝트로 가져올 수 있습니다.You can import OWIN support into your project by installing this package.

OWIN 미들웨어는 Func<IDictionary<string, object>, Task> 인터페이스 및 특정 키 설정(예: owin.ResponseBody)이 필요한 OWIN 사양을 준수합니다.OWIN middleware conforms to the OWIN specification, which requires a Func<IDictionary<string, object>, Task> interface, and specific keys be set (such as owin.ResponseBody). 다음과 같은 간단한 OWIN 미들웨어는 "Hello World"를 표시합니다.The following simple OWIN middleware displays "Hello World":

public Task OwinHello(IDictionary<string, object> environment)
{
    string responseText = "Hello World via OWIN";
    byte[] responseBytes = Encoding.UTF8.GetBytes(responseText);

    // OWIN Environment Keys: http://owin.org/spec/spec/owin-1.0.0.html
    var responseStream = (Stream)environment["owin.ResponseBody"];
    var responseHeaders = (IDictionary<string, string[]>)environment["owin.ResponseHeaders"];

    responseHeaders["Content-Length"] = new string[] { responseBytes.Length.ToString(CultureInfo.InvariantCulture) };
    responseHeaders["Content-Type"] = new string[] { "text/plain" };

    return responseStream.WriteAsync(responseBytes, 0, responseBytes.Length);
}

샘플 서명은 Task를 반환하고 OWIN에 필요한 IDictionary<string, object>를 수락합니다.The sample signature returns a Task and accepts an IDictionary<string, object> as required by OWIN.

다음 코드는 UseOwin 확장 메서드로 OwinHello 미들웨어(위에 표시된)를 ASP.NET 파이프라인에 추가하는 방법을 보여 줍니다.The following code shows how to add the OwinHello middleware (shown above) to the ASP.NET pipeline with the UseOwin extension method.

public void Configure(IApplicationBuilder app)
{
    app.UseOwin(pipeline =>
    {
        pipeline(next => OwinHello);
    });
}

OWIN 파이프라인 내에서 수행하도록 기타 작업을 구성할 수 있습니다.You can configure other actions to take place within the OWIN pipeline.

참고

응답 헤더는 응답 스트림에 대한 최초 작성 전에 수정되어야 합니다.Response headers should only be modified prior to the first write to the response stream.

참고

UseOwin에 대한 여러 번의 호출은 성능상의 이유로 권장되지 않습니다.Multiple calls to UseOwin is discouraged for performance reasons. OWIN 구성 요소는 함께 그룹화하는 경우 가장 잘 작동합니다.OWIN components will operate best if grouped together.

app.UseOwin(pipeline =>
{
    pipeline(async (next) =>
    {
        // do something before
        await OwinHello(new OwinEnvironment(HttpContext));
        // do something after
    });
});

OWIN 기반 서버에서 호스팅하는 ASP.NET 사용Using ASP.NET Hosting on an OWIN-based server

OWIN 기반 서버는 ASP.NET 응용 프로그램을 호스팅할 수 있습니다.OWIN-based servers can host ASP.NET applications. 이러한 서버는 Nowin, .NET OWIN 웹 서버입니다.One such server is Nowin, a .NET OWIN web server. 이 문서에 대한 샘플에서는 Nowin을 참조하고 자체 호스팅 ASP.NET Core가 가능한 IServer를 만드는 데 사용하는 프로젝트를 추가했습니다.In the sample for this article, I've included a project that references Nowin and uses it to create an IServer capable of self-hosting ASP.NET Core.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;

namespace NowinSample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseNowin()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .Build();

            host.Run();
        }
    }
}

IServerFeatures 속성 및 Start 메서드가 필요한 인터페이스입니다.IServer is an interface that requires a Features property and a Start method.

Start는 서버 구성 및 시작을 담당하며 이 경우 IServerAddressesFeature에서 구문 분석된 주소를 설정하는 일련의 흐름 API 호출을 통해 수행됩니다.Start is responsible for configuring and starting the server, which in this case is done through a series of fluent API calls that set addresses parsed from the IServerAddressesFeature. _builder 변수의 흐름 구성은 요청이 메서드의 앞부분에서 정의된 appFunc에 의해 처리되도록 지정합니다.Note that the fluent configuration of the _builder variable specifies that requests will be handled by the appFunc defined earlier in the method. Func는 들어오는 요청을 처리하도록 각 요청마다 호출됩니다.This Func is called on each request to process incoming requests.

Nowin 서버를 쉽게 추가하고 구성하도록 IWebHostBuilder 확장도 추가합니다.We'll also add an IWebHostBuilder extension to make it easy to add and configure the Nowin server.

using System;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.Extensions.DependencyInjection;
using Nowin;
using NowinSample;

namespace Microsoft.AspNetCore.Hosting
{
    public static class NowinWebHostBuilderExtensions
    {
        public static IWebHostBuilder UseNowin(this IWebHostBuilder builder)
        {
            return builder.ConfigureServices(services =>
            {
                services.AddSingleton<IServer, NowinServer>();
            });
        }

        public static IWebHostBuilder UseNowin(this IWebHostBuilder builder, Action<ServerBuilder> configure)
        {
            builder.ConfigureServices(services =>
            {
                services.Configure(configure);
            });
            return builder.UseNowin();
        }
    }
}

이 항목이 준비되어 있으면 이 사용자 지정 서버를 통해 Program.cs의 확장을 호출하여 ASP.NET Core 앱을 실행합니다.With this in place, invoke the extension in Program.cs to run an ASP.NET Core app using this custom server:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;

namespace NowinSample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseNowin()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .Build();

            host.Run();
        }
    }
}

ASP.NET 서버에 대해 자세히 알아봅니다.Learn more about ASP.NET Servers.

OWIN 기반 서버에서 ASP.NET Core 실행 및 해당 WebSocket 지원 사용Run ASP.NET Core on an OWIN-based server and use its WebSockets support

ASP.NET Core에서 OWIN 기반 서버 기능을 활용할 수 있는 방법의 또 다른 예는 WebSocket과 같은 기능에 대한 액세스입니다.Another example of how OWIN-based servers' features can be leveraged by ASP.NET Core is access to features like WebSockets. 이전 예제에서 사용되는 .NET OWIN 웹 서버에는 ASP.NET Core 응용 프로그램에서 활용할 수 있는 기본 제공되는 웹 소켓에 대한 지원이 있습니다.The .NET OWIN web server used in the previous example has support for Web Sockets built in, which can be leveraged by an ASP.NET Core application. 다음 예제에서는 웹 소켓을 지원하고 WebSocket을 통해 서버에 전송된 모든 항목을 다시 표시하는 단순한 웹앱을 보여 줍니다.The example below shows a simple web app that supports Web Sockets and echoes back everything sent to the server through WebSockets.

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            if (context.WebSockets.IsWebSocketRequest)
            {
                WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
                await EchoWebSocket(webSocket);
            }
            else
            {
                await next();
            }
        });

        app.Run(context =>
        {
            return context.Response.WriteAsync("Hello World");
        });
    }

    private async Task EchoWebSocket(WebSocket webSocket)
    {
        byte[] buffer = new byte[1024];
        WebSocketReceiveResult received = await webSocket.ReceiveAsync(
            new ArraySegment<byte>(buffer), CancellationToken.None);

        while (!webSocket.CloseStatus.HasValue)
        {
            // Echo anything we receive
            await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, received.Count), 
                received.MessageType, received.EndOfMessage, CancellationToken.None);

            received = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), 
                CancellationToken.None);
        }

        await webSocket.CloseAsync(webSocket.CloseStatus.Value, 
            webSocket.CloseStatusDescription, CancellationToken.None);
    }
}

샘플은 이전 것과 동일한 NowinServer를 사용하여 구성됩니다. 유일한 차이점은 응용 프로그램이 해당 Configure 메서드에서 구성되는 방식에 있습니다.This sample is configured using the same NowinServer as the previous one - the only difference is in how the application is configured in its Configure method. 간단한 websocket 클라이언트를 사용하는 테스트는 다음 응용 프로그램을 보여 줍니다.A test using a simple websocket client demonstrates the application:

웹 소켓 테스트 클라이언트

OWIN 환경OWIN environment

HttpContext를 사용하여 OWIN 환경을 구성할 수 있습니다.You can construct an OWIN environment using the HttpContext.


   var environment = new OwinEnvironment(HttpContext);
   var features = new OwinFeatureCollection(environment);

OWIN 키OWIN keys

OWIN은 HTTP 요청/응답 교환 전체에서 정보를 전달하는 IDictionary<string,object> 개체에 따라 달라집니다.OWIN depends on an IDictionary<string,object> object to communicate information throughout an HTTP Request/Response exchange. ASP.NET Core는 아래에 나열된 키를 구현합니다.ASP.NET Core implements the keys listed below. 기본 사양, 확장OWIN 키 지침 및 공통 키를 참조하세요.See the primary specification, extensions, and OWIN Key Guidelines and Common Keys.

요청 데이터(OWIN v1.0.0)Request data (OWIN v1.0.0)

KeyKey 값(형식)Value (type) 설명Description
owin.RequestSchemeowin.RequestScheme String
owin.RequestMethodowin.RequestMethod String
owin.RequestPathBaseowin.RequestPathBase String
owin.RequestPathowin.RequestPath String
owin.RequestQueryStringowin.RequestQueryString String
owin.RequestProtocolowin.RequestProtocol String
owin.RequestHeadersowin.RequestHeaders IDictionary<string,string[]>
owin.RequestBodyowin.RequestBody Stream

요청 데이터(OWIN v1.1.0)Request data (OWIN v1.1.0)

KeyKey 값(형식)Value (type) 설명Description
owin.RequestIdowin.RequestId String OptionalOptional

응답 데이터(OWIN v1.0.0)Response data (OWIN v1.0.0)

KeyKey 값(형식)Value (type) 설명Description
owin.ResponseStatusCodeowin.ResponseStatusCode int OptionalOptional
owin.ResponseReasonPhraseowin.ResponseReasonPhrase String OptionalOptional
owin.ResponseHeadersowin.ResponseHeaders IDictionary<string,string[]>
owin.ResponseBodyowin.ResponseBody Stream

기타 데이터(OWIN v1.0.0)Other data (OWIN v1.0.0)

KeyKey 값(형식)Value (type) 설명Description
owin.CallCancelledowin.CallCancelled CancellationToken
owin.Versionowin.Version String

공통 키Common keys

KeyKey 값(형식)Value (type) 설명Description
ssl.ClientCertificatessl.ClientCertificate X509Certificate
ssl.LoadClientCertAsyncssl.LoadClientCertAsync Func<Task>
server.RemoteIpAddressserver.RemoteIpAddress String
server.RemotePortserver.RemotePort String
server.LocalIpAddressserver.LocalIpAddress String
server.LocalPortserver.LocalPort String
server.IsLocalserver.IsLocal bool
server.OnSendingHeadersserver.OnSendingHeaders Action<Action<object>,object>

SendFiles v0.3.0SendFiles v0.3.0

KeyKey 값(형식)Value (type) 설명Description
sendfile.SendAsyncsendfile.SendAsync 대리자 시그니처 참조See delegate signature 요청당Per Request

불투명 v0.3.0Opaque v0.3.0

KeyKey 값(형식)Value (type) 설명Description
opaque.Versionopaque.Version String
opaque.Upgradeopaque.Upgrade OpaqueUpgrade 대리자 시그니처 참조See delegate signature
opaque.Streamopaque.Stream Stream
opaque.CallCancelledopaque.CallCancelled CancellationToken

WebSocket v0.3.0WebSocket v0.3.0

KeyKey 값(형식)Value (type) 설명Description
websocket.Versionwebsocket.Version String
websocket.Acceptwebsocket.Accept WebSocketAccept 대리자 시그니처 참조See delegate signature
websocket.AcceptAltwebsocket.AcceptAlt 비-사양Non-spec
websocket.SubProtocolwebsocket.SubProtocol String RFC6455 Section 4.2.2 5.5단계 참조See RFC6455 Section 4.2.2 Step 5.5
websocket.SendAsyncwebsocket.SendAsync WebSocketSendAsync 대리자 시그니처 참조See delegate signature
websocket.ReceiveAsyncwebsocket.ReceiveAsync WebSocketReceiveAsync 대리자 시그니처 참조See delegate signature
websocket.CloseAsyncwebsocket.CloseAsync WebSocketCloseAsync 대리자 시그니처 참조See delegate signature
websocket.CallCancelledwebsocket.CallCancelled CancellationToken
websocket.ClientCloseStatuswebsocket.ClientCloseStatus int OptionalOptional
websocket.ClientCloseDescriptionwebsocket.ClientCloseDescription String OptionalOptional

추가 자료Additional resources