/// <summary> /// Indicates whether this is a If-None-Match request with a matching etag. /// </summary> protected bool IsIfNoneMatchRequest(EntityTagHeaderValue currentEtag) { // CORE TODO Now using Microsoft.Net.Http.Headers, make sure it still has the same semantics // (null vs empty string, etc.) var headers = Request.GetTypedHeaders(); return(currentEtag != null && headers.IfNoneMatch != null && headers.IfNoneMatch.Any(entityTag => currentEtag.Compare(entityTag, false))); }
private static bool EtagEquals(HttpRequest request, EntityTagHeaderValue currentEtag) { // CORE TODO Double check this... before I found the GetTypedHeaders() extension method, I didn't think there was a typed implementation of the IfNoneMatch header // anymore, so I reimplemented based on the response caching middleware's implementation, leaving out the * match. See // https://github.com/aspnet/ResponseCaching/blob/52e8ffefb9b22c7c591aec15845baf07ed99356c/src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingMiddleware.cs#L454-L478 var ifNoneMatchHeader = request.Headers["If-None-Match"]; if (StringValues.IsNullOrEmpty(ifNoneMatchHeader)) { return(false); } return(EntityTagHeaderValue.TryParseList(ifNoneMatchHeader, out IList <Microsoft.Net.Http.Headers.EntityTagHeaderValue> ifNoneMatchEtags) && ifNoneMatchEtags.Any(t => currentEtag.Compare(t, useStrongComparison: false))); }
public void CompareUsingStrongComparison_NonEquivalentPairs_ReturnFalse(EntityTagHeaderValue left, EntityTagHeaderValue right) { Assert.False(left.Compare(right, useStrongComparison: true)); Assert.False(right.Compare(left, useStrongComparison: true)); }
public void CompareUsingWeakComparison_EquivalentPairs_ReturnTrue(EntityTagHeaderValue left, EntityTagHeaderValue right) { Assert.True(left.Compare(right, useStrongComparison: false)); Assert.True(right.Compare(left, useStrongComparison: false)); }
protected override async Task <IActionResult> CreateItemPutResponse(FileSystemInfoBase info, string localFilePath, bool itemExists) { // Check that we have a matching conditional If-Match request for existing resources if (itemExists) { var requestHeaders = Request.GetTypedHeaders(); var responseHeaders = Response.GetTypedHeaders(); // Get current etag EntityTagHeaderValue currentEtag = CreateEntityTag(info); // Existing resources require an etag to be updated. if (requestHeaders.IfMatch == null) { return(StatusCode(StatusCodes.Status412PreconditionFailed, Resources.VfsController_MissingIfMatch)); } bool isMatch = false; foreach (EntityTagHeaderValue etag in requestHeaders.IfMatch) { if (currentEtag.Compare(etag, false) || etag == EntityTagHeaderValue.Any) { isMatch = true; break; } } if (!isMatch) { responseHeaders.ETag = currentEtag; return(StatusCode(StatusCodes.Status412PreconditionFailed, Resources.VfsController_EtagMismatch)); } } // Save file try { using (Stream fileStream = GetFileWriteStream(localFilePath, fileExists: itemExists)) { try { await Request.Body.CopyToAsync(fileStream); } catch (Exception ex) { Tracer.TraceError(ex); return(StatusCode( StatusCodes.Status409Conflict, RS.Format(Resources.VfsController_WriteConflict, localFilePath, ex.Message))); } } // Return either 204 No Content or 201 Created response // Set updated etag for the file info.Refresh(); Response.SetEntityTagHeader(CreateEntityTag(info), info.LastWriteTimeUtc); return(itemExists ? NoContent() : StatusCode(StatusCodes.Status201Created)); } catch (Exception ex) { Tracer.TraceError(ex); return(StatusCode(StatusCodes.Status409Conflict, RS.Format(Resources.VfsController_WriteConflict, localFilePath, ex.Message))); } }