Last active
May 24, 2024 10:16
-
-
Save ranma42/a528555972f16c17ed1b840bfe7fbf5c to your computer and use it in GitHub Desktop.
Partial response hack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class LazyStream( | |
long length, | |
Func<Task<Stream>> factory | |
) : Stream { | |
public override long Position { | |
get => _position; | |
set { | |
if (value < 0 || value > length) { | |
throw new ArgumentOutOfRangeException(nameof(value), value, "Position must be between 0 and the length of the stream."); | |
} | |
if (value != _position) { | |
_position = value; | |
ResetStream(); | |
} | |
} | |
} | |
public override long Length => length; | |
public override bool CanWrite => false; | |
public override bool CanSeek => true; | |
public override bool CanRead => true; | |
private long _position; | |
private Stream? _stream; | |
public override int Read(byte[] buffer, int offset, int count) => | |
throw new NotSupportedException("Synchronous reads are not supported."); | |
public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken) { | |
if (buffer.IsEmpty || Position >= Length) { | |
return 0; | |
} | |
_stream ??= await factory(); | |
var result = await _stream.ReadAsync(buffer, cancellationToken); | |
_position += result; | |
return result; | |
} | |
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => | |
ReadAsync(buffer.AsMemory().Slice(offset, count), cancellationToken).AsTask(); | |
public override long Seek(long offset, SeekOrigin origin) => | |
Position = origin switch { | |
SeekOrigin.Begin => offset, | |
SeekOrigin.Current => Position + offset, | |
SeekOrigin.End => length + offset, | |
}; | |
public override void SetLength(long value) => throw new NotSupportedException(); | |
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); | |
public override void Flush() => throw new NotSupportedException(); | |
private void ResetStream() { | |
_stream?.Dispose(); | |
_stream = null; | |
} | |
protected override void Dispose(bool disposing) { | |
ResetStream(); | |
base.Dispose(disposing); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
app.MapGet("/example1/{key}", async (string key, IStore store) => | |
TypedResults.Stream | |
new LazyStream( | |
await store.GetSize(key), | |
() => httpContext.Response.GetTypedHeaders().ContentRange is { } contentRange | |
? store.GetPartialContent(key, new(contentRange.From, contentRange.To)) | |
: store.GetContent(key), | |
) | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment