public IActionResult PutStartAutomatedTestingEC2(bool start) { try { StringValues accessToken = new StringValues(); Request.Headers.TryGetValue("Authorization", out accessToken); if (accessToken.Count() == 0) { return(StatusCode(401, "Empty or no authorization header.")); } if (accessToken.FirstOrDefault().ToString() == null || accessToken.FirstOrDefault().ToString() == "") { return(StatusCode(401, "Empty or no authorization header.")); } if (_validation.CheckValidation(accessToken.ToString())) { _ec2Logic.StartAutomatedTestingEC2(); return(Ok()); } return(StatusCode(403, "This is an invalid access token.")); } catch (Exception e) { _logger.LogError(e.Message, e); return(StatusCode(500)); } }
public IActionResult DeleteArcadeMachine(int arcadeMachineId) { try { StringValues accessToken = new StringValues(); Request.Headers.TryGetValue("Authorization", out accessToken); if (accessToken.Count() == 0) { return(StatusCode(401, "Empty or no authorization header.")); } if (accessToken.FirstOrDefault().ToString() == null || accessToken.FirstOrDefault().ToString() == "") { return(StatusCode(401, "Empty or no authorization header.")); } if (_validation.CheckValidation(accessToken.ToString())) { _rdsLogic.DeleteArcadeMachine(arcadeMachineId); return(StatusCode(204)); } return(StatusCode(403, "This is an invalid access token.")); } catch (Exception e) { _logger.LogError(e.Message, e); return(StatusCode(500, e.Message)); } }
public IActionResult PostNewEntry([FromBody] NewEntry newEntry) { try { StringValues accessToken = new StringValues(); Request.Headers.TryGetValue("Authorization", out accessToken); if (accessToken.Count() == 0) { return(StatusCode(401, "Empty or no authorization header.")); } if (accessToken.FirstOrDefault().ToString() == null || accessToken.FirstOrDefault().ToString() == "") { return(StatusCode(401, "Empty or no authorization header.")); } if (_validation.CheckValidation(accessToken.ToString())) { Tuple <Games, int> tuple = _rdsLogic.PostNewEntry(newEntry); if (tuple.Item2 == 1) { return(StatusCode(409, "That game name already exists.")); } _ec2Logic.StartAutomatedTestingEC2(); return(StatusCode(201, tuple.Item1)); } return(StatusCode(403, "This is an invalid access token.")); } catch (Exception e) { _logger.LogError(e.Message, e); return(StatusCode(500, e.Message)); } }
public IActionResult GetInfo() { try { StringValues accessToken = new StringValues(); Request.Headers.TryGetValue("Authorization", out accessToken); if (accessToken.Count() == 0) { return(StatusCode(401, "Empty or no authorization header.")); } if (accessToken.FirstOrDefault().ToString() == null || accessToken.FirstOrDefault().ToString() == "") { return(StatusCode(401, "Empty or no authorization header.")); } if (_validation.CheckValidation(accessToken.ToString())) { return(Ok("Knights Arcade Restricted")); } return(StatusCode(403, "This is an invalid access token.")); } catch (Exception e) { _logger.LogError(e, e.Message); return(StatusCode(500, e.Message)); } }
public IActionResult SendEmail([FromBody] Email email) { try { StringValues accessToken = new StringValues(); Request.Headers.TryGetValue("Authorization", out accessToken); if (accessToken.Count() == 0) { return(StatusCode(401, "Empty or no authorization header.")); } if (accessToken.FirstOrDefault().ToString() == null || accessToken.FirstOrDefault().ToString() == "") { return(StatusCode(401, "Empty or no authorization header.")); } if (_validation.CheckValidation(accessToken.ToString())) { _smtpLogic.SendEmail(email); return(Ok()); } return(StatusCode(403, "This is an invalid access token.")); } catch (Exception e) { _logger.LogError(e.Message, e); return(StatusCode(500, e.Message)); } }
private static string EncodeQuery(string key, StringValues values, bool isKey) { string result = null; if (isKey) { result = key; } else { //array parameters are handled differently: see https://community.shopify.com/c/Shopify-APIs-SDKs/HMAC-calculation-vs-ids-arrays/td-p/261154 //https://github.com/nozzlegear/ShopifySharp/pull/437 //https://github.com/nozzlegear/ShopifySharp/issues/530 result = values.Count <= 1 && !key.EndsWith("[]") ? values.FirstOrDefault() : '[' + string.Join(", ", values.Select(v => '"' + v + '"')) + ']'; } if (string.IsNullOrEmpty(result)) { return(""); } //Important: Replace % before replacing &. Else second replace will replace those %25s. result = (result.Replace("%", "%25").Replace("&", "%26")) ?? ""; if (isKey) { result = result.Replace("=", "%3D").Replace("[]", ""); } return(result); }
/// <summary> /// Return the UserCulture of the httpRequest /// </summary> /// <param name="request"></param> /// <returns></returns> public static CultureInfo Culture(this HttpRequest request) { CultureInfo result = System.Threading.Thread.CurrentThread.CurrentUICulture; StringValues headerDataStringValues = StringValues.Empty; string firstAcceptLanguage = string.Empty; char[] MainSplit = new char[] { ';' }; // The header accept language needs splitting twice char[] SecondSplit = new char[] { ',' }; try { if (request.Headers?.TryGetValue("Accept-Language", out headerDataStringValues) == true) { firstAcceptLanguage = headerDataStringValues.FirstOrDefault(); firstAcceptLanguage = firstAcceptLanguage.Split(MainSplit)[0]; firstAcceptLanguage = firstAcceptLanguage.Split(SecondSplit)[0]; if (firstAcceptLanguage != string.Empty || firstAcceptLanguage != null) { result = new CultureInfo(firstAcceptLanguage); } } } catch { // falback to a default result = System.Threading.Thread.CurrentThread.CurrentUICulture; } return(result); }
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var token = new StringValues(); var tipo = new StringValues(); context.HttpContext.Request.Headers.TryGetValue("Authorization", out token); context.HttpContext.Request.Headers.TryGetValue("Tipo", out tipo); sharedInfo.Token = token.FirstOrDefault(); var tp = tipo.FirstOrDefault(); if (tp != null && sharedInfo.Token != null && !sharedInfo.Token.Contains("undefined")) { if (tp.ToUpper().Equals("USUARIO")) { var usuario = await _authService.GetUsuarioLogadoAsync(); sharedInfo.CodUsuario = usuario.GuidUsuario; sharedInfo.usuario = usuario; } else if (tp.ToUpper().Equals("EMPRESA")) { var empresa = await _authService.GetEmpresaLogadoAsync(); sharedInfo.CodEmpresa = empresa.Sub; sharedInfo.empresa = empresa; } } var resultContext = await next(); }
public async Task Invoke(HttpContext context) { var remoteIpAddress = context.Connection.RemoteIpAddress; if (context.Request.Path.StartsWithSegments("/api")) { var req = context.Request; StringValues autHeader = req.Headers["Authorization"]; if (autHeader.Any())// && authenticationScheme.Equals(req.Scheme, StringComparison.OrdinalIgnoreCase)) { var headerparams = autHeader.FirstOrDefault().ToString().Split(' '); var scheme = headerparams[0]; if (string.CompareOrdinal(scheme, authenticationScheme) == 0) { var rawAuthzHeader = headerparams[1]; var autherizationHeaderArray = GetAutherizationHeaderValues(rawAuthzHeader); if (autherizationHeaderArray != null) { var APPId = autherizationHeaderArray[0]; var incomingBase64Signature = autherizationHeaderArray[1]; var nonce = autherizationHeaderArray[2]; var requestTimeStamp = autherizationHeaderArray[3]; byte[] hash = await ComputeHash(req); var requestContentBase64String = ""; if (hash != null) { requestContentBase64String = Convert.ToBase64String(hash); } Console.WriteLine(); var isValid = isValidRequest(req, APPId, incomingBase64Signature, nonce, requestTimeStamp); if (isValid.Result) { await _next.Invoke(context); return; } else { context.Response.StatusCode = 405; //Method Not Allowed await context.Response.WriteAsync("Method Not Allowed"); return; } } } context.Response.StatusCode = 405; //Method Not Allowed await context.Response.WriteAsync("Method Not Allowed"); return; } } }
public async Task Invoke(HttpContext context, IKamajiContext db) { if (context.Request.Path.HasValue) { string[] arr = context.Request.Path.Value.Split('/');// ie "/api/Node/Register" if (arr.Length > 2) { string controllerTypeName = new StringBuilder().Append(nameof(Kamaji)).Append('.').Append(nameof(Kamaji.Controllers)).Append('.').Append(arr[2]).Append("Controller").ToString(); Type controllerType = Type.GetType(controllerTypeName); if (null != controllerType) { bool isValid = controllerType.GetCustomAttribute <DoNotAuthorizeAttribute>() != null;// doesn't matter if header exist or not. if (!isValid && context.Request.Headers is Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestHeaders headers) { StringValues values = headers.HeaderAuthorization; string token = values.FirstOrDefault(); if (!String.IsNullOrEmpty(token)) { arr = token.Split(' '); if (arr.Length == 2 || arr[0] == "Token")//you can later optimize the codes below using cache machanics. { string tokenValue = Serializer.FromBase64(arr[1]); Guid guid; if (Guid.TryParse(tokenValue, out guid)) { isValid = await db.Authes.GetBy(guid) != null; } } } } if (isValid) { await _next.Invoke(context); return; } } } } // context.Request.Headers[""] // Do something with context near the beginning of request processing. //Bunlara bitirince node belli aralıklarla //public virtual float CpuUsage { get; set; } //public virtual float MemoryUsage { get; set; } //public virtual DateTime LastConnectionTime { get; set; } //bu alnları doldursun. Ayrıca burada IObserver ile ekranda da gerçek zamanlı gösterecek alt yapı sağlansın. (Yani web uygulamasıyla kendisini observer ile köprü kursun) context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; await context.Response.WriteAsync("Access Denied 401"); }
/// <summary> /// Get IP address from HTTP context /// </summary> /// <returns>String of IP address</returns> public virtual string GetCurrentIpAddress() { if (!IsRequestAvailable()) { return(string.Empty); } string result = string.Empty; try { //first try to get IP address from the forwarded header if (_httpContextAccessor.HttpContext.Request.Headers != null) { //the X-Forwarded-For (XFF) HTTP header field is a de facto standard for identifying the originating IP address of a client //connecting to a web server through an HTTP proxy or load balancer string forwardedHttpHeaderKey = "X-FORWARDED-FOR"; StringValues forwardedHeader = _httpContextAccessor.HttpContext.Request.Headers[forwardedHttpHeaderKey]; if (!StringValues.IsNullOrEmpty(forwardedHeader)) { result = forwardedHeader.FirstOrDefault(); } } //if this header not exists try get connection remote IP address if (string.IsNullOrEmpty(result) && _httpContextAccessor.HttpContext.Connection.RemoteIpAddress != null) { result = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString(); } } catch { return(string.Empty); } //some of the validation if (result != null && result.Equals(IPAddress.IPv6Loopback.ToString(), StringComparison.InvariantCultureIgnoreCase)) { result = IPAddress.Loopback.ToString(); } //"TryParse" doesn't support IPv4 with port number if (IPAddress.TryParse(result ?? string.Empty, out IPAddress ip)) { //IP address is valid result = ip.ToString(); } else if (!string.IsNullOrEmpty(result)) { //remove port result = result.Split(':').FirstOrDefault(); } return(result); }
public ApiResult <ProductItemApiOutput> List([FromQuery] ProductApiInput parameter) { var apiOutput = Resolve <IProductService>().GetProductItems(parameter); var config = Resolve <IAutoConfigService>().GetValue <MemberDiscountConfig>(); if ((AutoModel?.BasicUser?.Id ?? 0) != 0) { parameter.LoginUserId = AutoModel.BasicUser.Id; } var loginUser = Resolve <IUserService>().GetSingle(parameter.LoginUserId); var isAdmin = Resolve <IUserService>().IsAdmin(parameter.LoginUserId); apiOutput.IsFrontShowPrice = true; // 不进行该判断 StringValues isTenant = string.Empty; if (Request.Headers.TryGetValue("zk-tenant", out isTenant)) { //如果有租户头 判断是否为空 ,如果不为空则表示有值 var tenant = Resolve <IUserService>().GetSingle(s => s.Mobile == isTenant.FirstOrDefault()); //如果有租户头 判断是否为空 ,如果不为空则表示有值 //if (isTenant.Where(s => !(string.IsNullOrEmpty(s) || s == "null"||s== "[object Null]")).Count() <= 0) if (tenant == null) //不是租户 则判断是否显示价格 { if (loginUser == null) { apiOutput.IsFrontShowPrice = false; apiOutput.PriceAlterText = config.PriceAlterText; } else if (!isAdmin && loginUser.GradeId == Guid.Parse("72BE65E6-3000-414D-972E-1A3D4A366000")) { apiOutput.IsFrontShowPrice = config.IsFrontShowPrice; apiOutput.PriceAlterText = config.PriceAlterText; } } } else { //如果没有该头部 直接判断 if (loginUser == null) { apiOutput.IsFrontShowPrice = false; apiOutput.PriceAlterText = config.PriceAlterText; } else if (!isAdmin && loginUser.GradeId == Guid.Parse("72BE65E6-3000-414D-972E-1A3D4A366000")) { apiOutput.IsFrontShowPrice = config.IsFrontShowPrice; apiOutput.PriceAlterText = config.PriceAlterText; } } return(ApiResult.Success(apiOutput)); }
private static string Get(this IHeaderDictionary headers, string key) { var values = new StringValues(); if (!headers.TryGetValue(key, out values)) { return(null); } return(values.FirstOrDefault()); }
private static void AddCriterion(IQuery query, string selector, StringValues selectorValues) { if (selectorValues.Count > 1) { query.Add(Criterion.In(selector, selectorValues)); } else { query.Add(Criterion.Eq(selector, selectorValues.FirstOrDefault())); } }
private String GetOperator <T>(IGridColumn <T> column) { StringValues values = column.Grid.Query[column.Grid.Name + "-" + column.Name + "-Op"]; if (column.IsMultiFilterable != true) { return(null); } return(values.FirstOrDefault()); }
public void InitAuthKey(AbstractRequestApiModel model) { StringValues authKey = StringValues.Empty; var request = HttpContext.Request; request.Headers.TryGetValue("AuthKey", out authKey); if (authKey.Count > 0) { var key = authKey.FirstOrDefault(); model.AuthKey = key; } }
public async Task Invoke(HttpContext httpContext) { try { var remoteIpAddress = httpContext.Connection.RemoteIpAddress; if (httpContext.Request.Path.StartsWithSegments("/api")) { var req = httpContext.Request; StringValues autHeader = req.Headers["Authorization"]; if (autHeader.Any())// && authenticationScheme.Equals(req.Scheme, StringComparison.OrdinalIgnoreCase)) { var headerparams = autHeader.FirstOrDefault().ToString().Split(' '); var scheme = headerparams[0]; var rawAuthzHeader = headerparams[1]; var autherizationHeaderArray = GetAutherizationHeaderValues(rawAuthzHeader); if (autherizationHeaderArray != null) { var APPId = autherizationHeaderArray[0]; var incomingBase64Signature = autherizationHeaderArray[1]; var nonce = autherizationHeaderArray[2]; var requestTimeStamp = autherizationHeaderArray[3]; //var isValid = isValidRequest(req, APPId, incomingBase64Signature, nonce, requestTimeStamp); //if (isValid.Result) //{ //var currentPrincipal = new GenericPrincipal(new GenericIdentity(APPId), null); //context.Principal = currentPrincipal; // } // else //{ //context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request); // } } if (httpContext.Request.Method != "POST") { httpContext.Response.StatusCode = 405; //Method Not Allowed await httpContext.Response.WriteAsync("Method Not Allowed"); return; } } } } catch (Exception ex) { } }
public CosignLoginResultModel Extract(IQueryCollection query) { StringValues states = query["state"]; string state = states.FirstOrDefault(); StringValues redirectUrls = query["redirectUrl"]; string redirectUrl = redirectUrls.FirstOrDefault(); StringValues codes = query[$"cosign-{_cosignClientName}"]; string code = codes.FirstOrDefault(); string token = code.Replace(" ", "+"); return(CosignLoginResultModel.Create(state, redirectUrl, token)); }
protected override async Task <AuthenticateResult> HandleAuthenticateAsync() { StringValues userIds = httpContextAccessor.HttpContext.Request.Headers["x-userid"]; var userId = userIds.FirstOrDefault(); StringValues userNames = httpContextAccessor.HttpContext.Request.Headers["x-username"]; var userName = userIds.FirstOrDefault(); IEnumerable <Claim> newClaims = claims .Select(v => userId != null && v.Type == ClaimsPrincipalExtensions.ObjectId ? new Claim("oid", userId) : v) .Select(v => userId != null && v.Type == "oid" ? new Claim("oid", userId) : v) .Select(v => userId != null && v.Type == ClaimTypes.NameIdentifier ? new Claim(ClaimTypes.NameIdentifier, userId) : v) .Select(v => userName != null && v.Type == ClaimTypes.Name ? new Claim(ClaimTypes.Name, userName) : v); var identity = new ClaimsIdentity(newClaims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); return(await Task.FromResult(AuthenticateResult.Success(ticket))); }
/// <summary> /// 取得token /// <para>作 者:蔡亚康</para> /// <para>创建时间:2019-03-27</para> /// </summary> /// <param name="context">HTTP请求上下文</param> /// <param name="tokenKey">token的KEY</param> /// <returns></returns> public static string GetToken(HttpContext context, string tokenKey) { string token = string.Empty; StringValues tokens = new StringValues(); IEnumerable <string> result = new List <string>(); bool rst = context.Request.Headers.TryGetValue(tokenKey, out tokens); if (rst) { token = tokens.FirstOrDefault(); } return(token); }
private bool TryGetRangeHeader(out string rangeHeader) { var rangeHeaderSv = new StringValues(); if (Request.Headers.TryGetValue("Range", out rangeHeaderSv)) { rangeHeader = rangeHeaderSv.FirstOrDefault(); return(true); } else { rangeHeader = string.Empty; return(false); } }
public override void OnActionExecuting(ActionExecutingContext context) { var key = "x-btcapi-usid"; StringValues values = new StringValues(""); if (context.HttpContext.Request.Headers.TryGetValue(key, out values)) { var usid = values.FirstOrDefault(); Guid result; if (!string.IsNullOrEmpty(usid) && Guid.TryParse(usid, out result)) { this.UsId = usid; } } }
public void OnAuthorization(AuthorizationFilterContext context) { // StringValues tokens = new StringValues(); if (context.HttpContext.Request.Headers.TryGetValue("session-token", out tokens)) { var token = tokens.FirstOrDefault(); if (tokenx.AuthenticationToken(token)) { RedirectToActionResult content = new RedirectToActionResult("NoAuth", "Exception", null); context.Result = content; } } }
internal static (string, OpenApiSpecVersion) GetContentTypeAndVersion(HttpContext context) { Contract.Assert(context != null); OpenApiSpecVersion specVersion = OpenApiSpecVersion.OpenApi3_0; // by default // $format=application/json;version=2.0 // $format=application/ymal;version=2.0 // accept=application/json;version3.0 HttpRequest request = context.Request; string dollarFormatValue = null; IQueryCollection queryCollection = request.Query; if (queryCollection.ContainsKey("$format")) { StringValues dollarFormat = queryCollection["$format"]; dollarFormatValue = dollarFormat.FirstOrDefault(); } if (dollarFormatValue != null) { MediaTypeHeaderValue parsedValue; bool success = MediaTypeHeaderValue.TryParse(dollarFormatValue, out parsedValue); if (success) { NameValueHeaderValue nameValueHeaderValue = parsedValue.Parameters.FirstOrDefault(p => p.Name == "version"); if (nameValueHeaderValue != null) { string version = nameValueHeaderValue.Value.Value; if (version == "2.0") { specVersion = OpenApiSpecVersion.OpenApi2_0; } } if (parsedValue.MediaType == "application/yaml") { return("application/yaml", specVersion); } return("application/json", specVersion); } } // default return("application/json", OpenApiSpecVersion.OpenApi3_0); }
public static string ExtractSlug(string host, StringValues serverNameValues, string devServerName, ILogger logger) { var serverName = serverNameValues.FirstOrDefault(); if (string.IsNullOrWhiteSpace(host)) { logger.LogDebug( "'Host' HTTP header not found or empty. Cannot infer the tenant slug. " + "Assuming empty slug -> default tenant."); return(""); } // 'Host' HTTP header is not empty, but what about 'PSK-ServerName' header? if (!string.IsNullOrWhiteSpace(serverName)) { var index = host.IndexOf(serverName); if (index != -1) { // serverName is a substring of Host HTTP header // likely for production, will either return some string or an empty slug return(host.Substring(0, index).TrimEnd('.').ToLower()); } var msg = $"Host = '{host}', ServerName = '{serverName}'"; logger.LogDebug( "'Host' header doesn't contain the value of 'PSK-ServerName'. Check proxy configuration. " + "Assuming empty slug -> default tenant. " + msg); return(""); } logger.LogDebug( "'PSK-ServerName' HTTP header not found or empty. Assuming development environment. " + $"DevServerName = '{devServerName}'"); var idx = host.IndexOf(devServerName); if (idx != -1) { return(host.Substring(0, idx).TrimEnd('.')); } var err = $"Host = '{host}', Config.DevServerName = '{devServerName}'"; logger.LogDebug( "'Host' header doesn't contain the value of 'DevServerName'. Check your environment. " + "Assuming empty slug -> default tenant. " + err); return(""); }
internal static CurrentUser GetCurrentUser(HttpContext httpContext, RedisCache redisCache) { StringValues sessionId = StringValues.Empty; httpContext.Request.Headers.TryGetValue("VLSession", out sessionId); if (sessionId.FirstOrDefault().IsNullOrEmpty()) { return(null); } var currentUser = redisCache.Get <CurrentUser>(sessionId); if (currentUser == null) { throw new NotImplementedException("当前用户不存在"); } return(currentUser); }
public override void OnActionExecuting(ActionExecutingContext filterContext) { var allowedMMetode = new[] { "api/LockDoor/RegisterLogin", "api/LockDoor/OpenDoor" , "api/LockDoor/GetJalanSetapak", "api/LockDoor/GetDoorChecking", "api/Values", "api/Values/Get" , "api/Values/GetValue", "api/Values/GetSimpanAsync" }; StringValues headerValues = ""; var userId = string.Empty; string currentTemplate = filterContext.ActionDescriptor.AttributeRouteInfo.Template; string checker = string.Empty; string TheSun = string.Empty; if (allowedMMetode.Contains(currentTemplate)) { string akuboleh = ""; } else { if (filterContext.HttpContext.Request.Headers.TryGetValue("TheSun", out headerValues)) { TheSun = headerValues.FirstOrDefault(); } if (TheSun == "TheSun") { throw new ArgumentNullException("filterContext"); } else { if (TheSun.Contains("TheSun")) { checker = TheSun.Replace("TheSun", string.Empty).Trim(); var checkerResult = cacher.GetValue(checker); if (checkerResult == null) { throw new ArgumentNullException("filterContext"); } else { } } else { throw new ArgumentNullException("filterContext"); } } } }
private static string EncodeQuery(StringValues values, bool isKey) { var s = values.FirstOrDefault(); //Important: Replace % before replacing &. Else second replace will replace those %25s. if (s == null) { return(string.Empty); } var output = s.Replace("%", "%25").Replace("&", "%26"); if (isKey) { output = output.Replace("=", "%3D"); } return(output); }
/// <summary> /// 获取回传参数 /// </summary> /// <param name="name"></param> /// <returns></returns> protected string GetParam(string name) { StringValues value = StringValues.Empty; if (Request.Method == "POST") { value = Request.Form[name]; } if (value == StringValues.Empty) { value = Request.Query[name]; } if (value == StringValues.Empty) { return(""); } return(value.FirstOrDefault()); }
private static string EncodeQuery(StringValues values, bool isKey) { string s = values.FirstOrDefault(); if (string.IsNullOrEmpty(s)) { return(""); } //Important: Replace % before replacing &. Else second replace will replace those %25s. string output = (s.Replace("%", "%25").Replace("&", "%26")) ?? ""; if (isKey) { output = output.Replace("=", "%3D"); } return(output); }
private static string Get(this IHeaderDictionary headers, string key) { var values = new StringValues(); if (!headers.TryGetValue(key, out values)) { return null; } return values.FirstOrDefault(); }