ASP.NET Core의 HTTP 로깅

참고 항목

이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Important

이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.

현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

HTTP 로깅은 들어오는 HTTP 요청 및 HTTP 응답에 대한 정보를 기록하는 미들웨어입니다. HTTP 로깅은 다음의 로그를 제공합니다.

  • HTTP 요청 정보
  • 일반 속성
  • 헤더
  • 본문
  • HTTP 응답 정보

HTTP 로깅은 다음을 수행할 수 있습니다.

  • 모든 요청 및 응답 또는 특정 조건을 충족하는 요청 및 응답만 기록합니다.
  • 요청 및 응답이 기록되는 부분을 선택합니다.
  • 로그에서 중요한 정보를 수정할 수 있습니다.

HTTP 로깅 은 특히 요청 및 응답 본문을 로깅할 때 앱의 성능을 저하시킬 수 있습니다. 로그할 필드를 선택할 때 성능에 미치는 영향을 고려하고 선택한 로깅 속성이 성능에 미치는 영향을 테스트하세요.

Warning

HTTP 로깅은 PII(개인 식별 정보)를 기록할 수 있습니다. 위험성을 고려해 중요한 정보를 로그하지 않도록 하세요.

HTTP 로깅 사용

HTTP 로깅은 다음 예제와 같이 호출 AddHttpLogging 하여 사용하도록 설정됩니다 UseHttpLogging.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(o => { });

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Hello World!");

app.Run();

이전 호출 AddHttpLogging 예제의 빈 람다는 기본 구성을 사용하여 미들웨어를 추가합니다. 기본적으로 HTTP 로깅은 요청 및 응답에 대한 경로, 상태 코드 및 헤더와 같은 일반적인 속성을 기록합니다.

HTTP 로그가 표시되도록 "LogLevel": { 수준에서 다음 줄을 appsettings.Development.json 파일에 추가:

 "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"

기본 구성을 사용하면 요청 및 응답이 다음 예제와 유사한 메시지 쌍으로 기록됩니다.

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
      Request:
      Protocol: HTTP/2
      Method: GET
      Scheme: https
      PathBase:
      Path: /
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
      Host: localhost:52941
      User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.61
      Accept-Encoding: gzip, deflate, br
      Accept-Language: en-US,en;q=0.9
      Upgrade-Insecure-Requests: [Redacted]
      sec-ch-ua: [Redacted]
      sec-ch-ua-mobile: [Redacted]
      sec-ch-ua-platform: [Redacted]
      sec-fetch-site: [Redacted]
      sec-fetch-mode: [Redacted]
      sec-fetch-user: [Redacted]
      sec-fetch-dest: [Redacted]
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
      Response:
      StatusCode: 200
      Content-Type: text/plain; charset=utf-8
      Date: Tue, 24 Oct 2023 02:03:53 GMT
      Server: Kestrel

HTTP 로깅 옵션

HTTP 로깅 미들웨어에 대한 전역 옵션을 구성하려면 람다를 사용하여 호출 AddHttpLoggingProgram.cs하여 구성 HttpLoggingOptions합니다.

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
    logging.CombineLogs = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

참고 항목

앞의 샘플 및 다음 샘플 UseHttpLogging 에서는 정 UseStaticFiles적 파일에 대해 HTTP 로깅을 사용할 수 없도록 호출됩니다. 정적 파일 HTTP 로깅을 사용하도록 설정하려면 앞에 호출 UseHttpLogging 합니다 UseStaticFiles.

LoggingFields

HttpLoggingOptions.LoggingFields는 로그 요청 및 응답의 특정 부분을 구성하는 열거형 플래그입니다. HttpLoggingOptions.LoggingFields 기본값은 RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders입니다.

RequestHeadersResponseHeaders

RequestHeadersResponseHeaders 깅되는 HTTP 헤더 집합입니다. 헤더 값은 이러한 컬렉션에 있는 헤더 이름에 대해서만 기록됩니다. 헤더 값 sec-ch-uaRequestHeaders기록되도록 다음 코드가 추가 sec-ch-ua 됩니다. MyResponseHeader 헤더 값 MyResponseHeaderResponseHeaders기록되도록 추가됩니다. 이러한 줄이 제거되면 이러한 헤더의 값은 다음과 같습니다 [Redacted].

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
    logging.CombineLogs = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

MediaTypeOptions

MediaTypeOptions는 특정 미디어 유형에 사용할 인코딩을 선택하기 위한 구성을 제공합니다.

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
    logging.CombineLogs = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

이 방법은 기본적으로 기록되지 않은 데이터에 대한 로깅을 사용하도록 설정하는 데도 사용할 수 있습니다(예: 양식 데이터, 미디어 형식 또는 multipart/form-data같은 application/x-www-form-urlencoded 형식이 있을 수 있음).

MediaTypeOptions 메서드

RequestBodyLogLimitResponseBodyLogLimit

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
    logging.CombineLogs = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

CombineLogs

요청 및 응답에 true 대해 사용하도록 설정된 모든 로그를 마지막에 하나의 로그에 통합하도록 미들웨어를 구성하도록 설정합니다CombineLogs. 여기에는 요청, 요청 본문, 응답, 응답 본문 및 기간이 포함됩니다.

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
    logging.CombineLogs = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

엔드포인트별 구성

최소 API 앱의 엔드포인트별 구성의 경우 확장 메서드를 WithHttpLogging 사용할 수 있습니다. 다음 예제에서는 하나의 엔드포인트에 대해 HTTP 로깅을 구성하는 방법을 보여 줍니다.

app.MapGet("/response", () => "Hello World! (logging response)")
    .WithHttpLogging(HttpLoggingFields.ResponsePropertiesAndHeaders);

컨트롤러를 사용하는 앱의 엔드포인트별 구성의 [HttpLogging] 경우 특성을 사용할 수 있습니다. 이 특성은 다음 예제와 같이 최소 API 앱에서도 사용할 수 있습니다.

app.MapGet("/duration", [HttpLogging(loggingFields: HttpLoggingFields.Duration)]
    () => "Hello World! (logging duration)");

IHttpLoggingInterceptor

IHttpLoggingInterceptor 는 기록되는 세부 정보를 사용자 지정하기 위해 요청당 및 응답별 콜백을 처리하도록 구현할 수 있는 서비스의 인터페이스입니다. 엔드포인트별 로그 설정이 먼저 적용된 다음 이러한 콜백에서 재정의될 수 있습니다. 구현은 다음을 수행할 수 있습니다.

  • 요청 또는 응답을 검사합니다.
  • 을 사용하거나 사용하지 않도록 설정합니다 HttpLoggingFields.
  • 기록되는 요청 또는 응답 본문의 양을 조정합니다.
  • 로그에 사용자 지정 필드를 추가합니다.

에서 IHttpLoggingInterceptor 호출 AddHttpLoggingInterceptor<T> 하여 구현을 등록합니다 Program.cs. 여러 IHttpLoggingInterceptor 인스턴스가 등록된 경우 등록된 순서대로 실행됩니다.

다음 예제에서는 구현을 등록하는 IHttpLoggingInterceptor 방법을 보여줍니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.Duration;
});
builder.Services.AddHttpLoggingInterceptor<SampleHttpLoggingInterceptor>();

다음 예제는 구현입니다.IHttpLoggingInterceptor

  • 요청 메서드를 검사하고 POST 요청에 대한 로깅을 사용하지 않도록 설정합니다.
  • POST가 아닌 요청의 경우:
    • 요청 경로, 요청 헤더 및 응답 헤더를 수정합니다.
    • 요청 및 응답 로그에 사용자 지정 필드 및 필드 값을 추가합니다.
using Microsoft.AspNetCore.HttpLogging;

namespace HttpLoggingSample;

internal sealed class SampleHttpLoggingInterceptor : IHttpLoggingInterceptor
{
    public ValueTask OnRequestAsync(HttpLoggingInterceptorContext logContext)
    {
        if (logContext.HttpContext.Request.Method == "POST")
        {
            // Don't log anything if the request is a POST.
            logContext.LoggingFields = HttpLoggingFields.None;
        }

        // Don't enrich if we're not going to log any part of the request.
        if (!logContext.IsAnyEnabled(HttpLoggingFields.Request))
        {
            return default;
        }

        if (logContext.TryDisable(HttpLoggingFields.RequestPath))
        {
            RedactPath(logContext);
        }

        if (logContext.TryDisable(HttpLoggingFields.RequestHeaders))
        {
            RedactRequestHeaders(logContext);
        }

        EnrichRequest(logContext);

        return default;
    }

    public ValueTask OnResponseAsync(HttpLoggingInterceptorContext logContext)
    {
        // Don't enrich if we're not going to log any part of the response
        if (!logContext.IsAnyEnabled(HttpLoggingFields.Response))
        {
            return default;
        }

        if (logContext.TryDisable(HttpLoggingFields.ResponseHeaders))
        {
            RedactResponseHeaders(logContext);
        }

        EnrichResponse(logContext);

        return default;
    }

    private void RedactPath(HttpLoggingInterceptorContext logContext)
    {
        logContext.AddParameter(nameof(logContext.HttpContext.Request.Path), "RedactedPath");
    }

    private void RedactRequestHeaders(HttpLoggingInterceptorContext logContext)
    {
        foreach (var header in logContext.HttpContext.Request.Headers)
        {
            logContext.AddParameter(header.Key, "RedactedHeader");
        }
    }

    private void EnrichRequest(HttpLoggingInterceptorContext logContext)
    {
        logContext.AddParameter("RequestEnrichment", "Stuff");
    }

    private void RedactResponseHeaders(HttpLoggingInterceptorContext logContext)
    {
        foreach (var header in logContext.HttpContext.Response.Headers)
        {
            logContext.AddParameter(header.Key, "RedactedHeader");
        }
    }

    private void EnrichResponse(HttpLoggingInterceptorContext logContext)
    {
        logContext.AddParameter("ResponseEnrichment", "Stuff");
    }
}

이 인터셉터를 사용하면 HTTP 로깅이 로깅되도록 구성된 경우에도 POST 요청이 로그 HttpLoggingFields.All를 생성하지 않습니다. GET 요청은 다음 예제와 유사한 로그를 생성합니다.

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
      Request:
      Path: RedactedPath
      Accept: RedactedHeader
      Host: RedactedHeader
      User-Agent: RedactedHeader
      Accept-Encoding: RedactedHeader
      Accept-Language: RedactedHeader
      Upgrade-Insecure-Requests: RedactedHeader
      sec-ch-ua: RedactedHeader
      sec-ch-ua-mobile: RedactedHeader
      sec-ch-ua-platform: RedactedHeader
      sec-fetch-site: RedactedHeader
      sec-fetch-mode: RedactedHeader
      sec-fetch-user: RedactedHeader
      sec-fetch-dest: RedactedHeader
      RequestEnrichment: Stuff
      Protocol: HTTP/2
      Method: GET
      Scheme: https
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
      Response:
      Content-Type: RedactedHeader
      MyResponseHeader: RedactedHeader
      ResponseEnrichment: Stuff
      StatusCode: 200
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[4]
      ResponseBody: Hello World!
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[8]
      Duration: 2.2778ms

우선 순위의 로깅 구성 순서

다음 목록에서는 로깅 구성의 우선 순위 순서를 보여 줍니다.

  1. 에서 전역 구성 HttpLoggingOptions, 호출 AddHttpLogging을 통해 설정합니다.
  2. 특성 또는 확장 메서드의 [HttpLogging] 엔드포인트별 구성이 전역 구성을 재정의 WithHttpLogging 합니다.
  3. IHttpLoggingInterceptor 는 결과와 함께 호출되며 요청당 구성을 추가로 수정할 수 있습니다.

HTTP 로깅은 들어오는 HTTP 요청 및 HTTP 응답에 대한 정보를 로그하는 미들웨어입니다. HTTP 로깅은 다음의 로그를 제공합니다.

  • HTTP 요청 정보
  • 일반 속성
  • 헤더
  • 본문
  • HTTP 응답 정보

HTTP 로깅이 유용한 몇 가지 시나리오는 다음과 같습니다.

  • 들어오는 요청 및 응답에 대한 정보를 기록합니다.
  • 요청 및 응답의 어느 부분이 로그되는지 필터링합니다.
  • 로그할 헤더를 필터링합니다.

HTTP 로깅은 특히 요청 및 응답 본문을 로그할 때 앱의 성능을 저하시킬 수 있습니다. 로그할 필드를 선택할 때 성능에 미치는 영향을 고려하고 선택한 로깅 속성이 성능에 미치는 영향을 테스트하세요.

Warning

HTTP 로깅 사용 시 PII(개인 식별 정보)가 로그될 가능성이 있습니다. 위험성을 고려해 중요한 정보를 로그하지 않도록 하세요.

HTTP 로깅 사용

HTTP 로깅은 HTTP 로깅 미들웨어를 추가하는 UseHttpLogging을 통해 사용할 수 있습니다.

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Hello World!");

app.Run();

기본적으로 HTTP 로깅은 요청 및 응답에 대한 경로, 상태 코드, 헤더와 같은 공통 속성을 로그합니다. HTTP 로그가 표시되도록 "LogLevel": { 수준에서 다음 줄을 appsettings.Development.json 파일에 추가:

 "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"

출력은 LogLevel.Information에서 단일 메시지로 로그됩니다.

샘플 요청 출력

HTTP 로깅 옵션

HTTP 로깅 미들웨어를 구성하려면 Program.cs에서 AddHttpLogging을 호출합니다.

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

참고 항목

앞의 샘플 및 다음 샘플 UseHttpLogging 에서는 정 UseStaticFiles적 파일에 대해 HTTP 로깅을 사용할 수 없도록 호출됩니다. 정적 파일 HTTP 로깅을 사용하도록 설정하려면 앞에 호출 UseHttpLogging 합니다 UseStaticFiles.

LoggingFields

HttpLoggingOptions.LoggingFields는 로그 요청 및 응답의 특정 부분을 구성하는 열거형 플래그입니다. HttpLoggingOptions.LoggingFields 기본값은 RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders입니다.

RequestHeaders

Headers는 로그할 수 있는 HTTP 요청 헤더의 집합입니다. 헤더 값은 이 컬렉션에 있는 헤더 이름에 대해서만 로그됩니다. 다음 코드는 요청 헤더 "sec-ch-ua"를 로그합니다. logging.RequestHeaders.Add("sec-ch-ua");가 제거된 경우 요청 헤더 "sec-ch-ua"의 값이 수정됩니다. 다음 강조 표시된 코드는 HttpLoggingOptions.RequestHeadersHttpLoggingOptions.ResponseHeaders를 호출합니다.

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

MediaTypeOptions

MediaTypeOptions는 특정 미디어 유형에 사용할 인코딩을 선택하기 위한 구성을 제공합니다.

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

이 방법을 사용하여 기본적으로 기록되지 않은 데이터에 대한 로깅을 사용하도록 설정할 수도 있습니다(예: 양식 데이터(예: application/x-www-form-urlencoded 미디어 형식 또는 multipart/form-data)).

MediaTypeOptions 메서드

RequestBodyLogLimitResponseBodyLogLimit

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();