prometheus-net

Форк
0
/
PushStreamContentInternal.cs 
84 строки · 3.8 Кб
1
// Copyright (c) .NET Foundation. All rights reserved.
2
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3
// Simplified for prometheus-net for dependency reduction reasons.
4

5
using System.Diagnostics.CodeAnalysis;
6
using System.Net;
7
using System.Net.Http.Headers;
8

9
namespace Prometheus;
10

11
/// <summary>
12
/// Provides an <see cref="HttpContent"/> implementation that exposes an output <see cref="Stream"/>
13
/// which can be written to directly. The ability to push data to the output stream differs from the 
14
/// <see cref="StreamContent"/> where data is pulled and not pushed.
15
/// </summary>
16
sealed class PushStreamContentInternal : HttpContent
17
{
18
    private readonly Func<Stream, HttpContent, TransportContext?, Task> _onStreamAvailable;
19

20
    private static readonly MediaTypeHeaderValue OctetStreamHeaderValue = MediaTypeHeaderValue.Parse("application/octet-stream");
21

22
    /// <summary>
23
    /// Initializes a new instance of the <see cref="PushStreamContentInternal"/> class with the given <see cref="MediaTypeHeaderValue"/>.
24
    /// </summary>
25
    public PushStreamContentInternal(Func<Stream, HttpContent, TransportContext?, Task> onStreamAvailable, MediaTypeHeaderValue mediaType)
26
    {
27
        _onStreamAvailable = onStreamAvailable;
28
        Headers.ContentType = mediaType ?? OctetStreamHeaderValue;
29
    }
30

31
    /// <summary>
32
    /// When this method is called, it calls the action provided in the constructor with the output 
33
    /// stream to write to. Once the action has completed its work it closes the stream which will 
34
    /// close this content instance and complete the HTTP request or response.
35
    /// </summary>
36
    /// <param name="stream">The <see cref="Stream"/> to which to write.</param>
37
    /// <param name="context">The associated <see cref="TransportContext"/>.</param>
38
    /// <returns>A <see cref="Task"/> instance that is asynchronously serializing the object's content.</returns>
39
    [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exception is passed as task result.")]
40
    protected override async Task SerializeToStreamAsync(Stream stream, TransportContext? context)
41
    {
42
        TaskCompletionSource<bool> serializeToStreamTask = new TaskCompletionSource<bool>();
43

44
        Stream wrappedStream = new CompleteTaskOnCloseStream(stream, serializeToStreamTask);
45
        await _onStreamAvailable(wrappedStream, this, context);
46

47
        // wait for wrappedStream.Close/Dispose to get called.
48
        await serializeToStreamTask.Task;
49
    }
50

51
    /// <summary>
52
    /// Computes the length of the stream if possible.
53
    /// </summary>
54
    /// <param name="length">The computed length of the stream.</param>
55
    /// <returns><c>true</c> if the length has been computed; otherwise <c>false</c>.</returns>
56
    protected override bool TryComputeLength(out long length)
57
    {
58
        // We can't know the length of the content being pushed to the output stream.
59
        length = -1;
60
        return false;
61
    }
62

63
    internal class CompleteTaskOnCloseStream : DelegatingStreamInternal
64
    {
65
        private TaskCompletionSource<bool> _serializeToStreamTask;
66

67
        public CompleteTaskOnCloseStream(Stream innerStream, TaskCompletionSource<bool> serializeToStreamTask)
68
            : base(innerStream)
69
        {
70
            _serializeToStreamTask = serializeToStreamTask;
71
        }
72

73
        [SuppressMessage(
74
            "Microsoft.Usage",
75
            "CA2215:Dispose methods should call base class dispose",
76
            Justification = "See comments, this is intentional.")]
77
        protected override void Dispose(bool disposing)
78
        {
79
            // We don't dispose the underlying stream because we don't own it. Dispose in this case just signifies
80
            // that the user's action is finished.
81
            _serializeToStreamTask.TrySetResult(true);
82
        }
83
    }
84
}
85

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.