[OCA] 파워플랫폼 마스터즈 - End Point 리팩토링(1)

오경찬·2022년 8월 18일
0

마스터즈 합류

챌린저스를 끝내고 마스터즈 인원 발표를 기다리고 있는데 멘토님께서 리드맨티 제안을 하셨다!

하지만 다른것도 바쁘고 많을 시간을 투자하지 못하지 때문에 죄송하다고 일반 팀원으로 하고 싶다고 말씀드렸다.

그결과 4번 번호로 합류하게 되었다~!~!
(분명 15명이였는데..?)

엔드포인트 리팩토링

3개의 팀으로 나뉘어서 우리팀은 엔드포인트 리펙토링을 담당하게되었다.

일단 이번주는 nt-sms Trigger 폴더의 코드들을 어떻게 리팩토링 할것인지에 대한 워크플로우를 생각해오기로 했다.

Trigger

  • GetMessage : 발송 단일 검색
  • ListMessages : 발송 목록 검색
  • ListMessageStatus : 검색 api
  • ListSenders : 발신번호 목록 검색
  • SendMessages : 문자메세지 보내기
//GetMessage.cs
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

using Aliencube.AzureFunctions.Extensions.Common;

using FluentValidation;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;

using Toast.Common.Builders;
using Toast.Common.Configurations;
using Toast.Common.Extensions;
using Toast.Common.Models;
using Toast.Common.Validators;
using Toast.Sms.Configurations;
using Toast.Sms.Models;
using Toast.Sms.Validators;

namespace Toast.Sms.Triggers
{
    public class GetMessage
    {
        private readonly ToastSettings<SmsEndpointSettings> _settings;
        private readonly IValidator<GetMessageRequestQueries> _validator;
        private readonly HttpClient _http;
        private readonly ILogger<GetMessage> _logger;

        public GetMessage(ToastSettings<SmsEndpointSettings> settings, IValidator<GetMessageRequestQueries> validator, IHttpClientFactory factory, ILogger<GetMessage> log)
        {
            this._settings = settings.ThrowIfNullOrDefault();
            this._validator = validator.ThrowIfNullOrDefault();
            this._http = factory.ThrowIfNullOrDefault().CreateClient("messages");
            this._logger = log.ThrowIfNullOrDefault();
        }

        [FunctionName(nameof(GetMessage))]
        //OpenApiParameter 모음
        [OpenApiOperation(operationId: "Messages.Get", tags: new[] { "messages" })]
        [OpenApiSecurity("app_auth", SecuritySchemeType.Http, Scheme = OpenApiSecuritySchemeType.Basic, Description = "Toast API basic auth")]
        // [OpenApiSecurity("app_key", SecuritySchemeType.ApiKey, Name = "x-app-key", In = OpenApiSecurityLocationType.Header, Description = "Toast app key")]
        // [OpenApiSecurity("secret_key", SecuritySchemeType.ApiKey, Name = "x-secret-key", In = OpenApiSecurityLocationType.Header, Description = "Toast secret key")]
        // [OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "x-functions-key", In = OpenApiSecurityLocationType.Header, Description = "Functions API key")]
        [OpenApiParameter(name: "requestId", Type = typeof(string), In = ParameterLocation.Path, Required = true, Description = "SMS request ID")]
        [OpenApiParameter(name: "recipientSeq", Type = typeof(int), In = ParameterLocation.Query, Required = true, Description = "SMS request sequence number")]
        [OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(GetMessageResponse), Example = typeof(GetMessageResponseModelExample), Description = "The OK response")]
        [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.BadRequest, Description = "The input was invalid")]
        [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.InternalServerError, Description = "The service has got an unexpected error")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "GET", Route = "messages/{requestId:regex(^\\d+\\w+$)}")] HttpRequest req,
            string requestId)
        {
            _logger.LogInformation("C# HTTP trigger function processed a request.");

            var headers = default(RequestHeaderModel);
            try
            {
                headers = req.To<RequestHeaderModel>(useBasicAuthHeader: true).Validate();
                // headers = await req.To<RequestHeaderModel>(SourceFrom.Header).Validate().ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                return new BadRequestResult();
            }

            var queries = default(GetMessageRequestQueries);
            try 
            {
                queries = await req.To<GetMessageRequestQueries>(SourceFrom.Query).Validate(this._validator).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                return new BadRequestResult();
            }

            var paths = new GetMessageRequestPaths() { RequestId = requestId };
// query parameter추가
            var requestUrl = new RequestUrlBuilder()
                .WithSettings(this._settings, this._settings.Endpoints.GetMessage)
                .WithHeaders(headers)
                .WithQueries(queries)
                .WithPaths(paths).Build();
// 세팅값, 해더, 쿼리값, 패치 넣고 빌드
            this._http.DefaultRequestHeaders.Add("X-Secret-Key", headers.SecretKey);
            var result = await this._http.GetAsync(requestUrl).ConfigureAwait(false);
// 시크릿값 넣어줌
            var payload = await result.Content.ReadAsAsync<GetMessageResponse>().ConfigureAwait(false);

            return new OkObjectResult(payload);
        }
    }
}

저번주에 사용해봤던 API의 흐름이다. 사용한것을 직접 코드로 보니 어느정도는 흐름을 알게된거 같다.

profile
코린이 입니당 :)

0개의 댓글