/// <summary>
        /// Checks whether the media-type is supported
        /// </summary>
        /// <param name="compressionManager">HTTP compression manager</param>
        /// <param name="mediaType">Media-type</param>
        /// <returns>Result of check (true - supported; false - not supported)</returns>
        public static bool IsSupportedMediaType(this IHttpCompressionManager compressionManager, string mediaType)
        {
            if (string.IsNullOrWhiteSpace(mediaType))
            {
                return(false);
            }

            Func <string, bool> supportedMediaTypePredicate = compressionManager.SupportedMediaTypePredicate;

            if (supportedMediaTypePredicate != null)
            {
                return(supportedMediaTypePredicate(mediaType));
            }

            return(MediaTypeHelpers.IsTextBasedMediaType(mediaType));
        }
示例#2
0
        public async Task <IActionResult> Upload(string filename)
        {
            if (string.IsNullOrWhiteSpace(filename))
            {
                return(BadRequest("`filename` query parameter must be supplied"));
            }

            var name      = Path.GetFileNameWithoutExtension(filename);
            var extension = Path.GetExtension(filename);

            var upload = new Upload
            {
                Id        = await _slugGenerator.GenerateSlugAsync(Request.HttpContext.RequestAborted),
                Name      = name,
                Extension = extension,
                OriginalFileNameWithExtension = Path.GetFileName(filename),
                MediaType    = MediaTypeHelpers.GetMediaTypeFromExtension(extension),
                CodeLanguage = CodeLanguageHelpers.GetLanageFromExtension(extension),
                Length       = Request.ContentLength.GetValueOrDefault(),
                UserId       = _userManager.GetUserId(User),
                CreatedBy    = _userManager.GetUserName(User)
            };

            await _context.Uploads.AddAsync(upload, Request.HttpContext.RequestAborted);

            await _context.SaveChangesAsync(Request.HttpContext.RequestAborted);

            await _store.WriteAllBytesAsync(upload, Request.Body, Request.HttpContext.RequestAborted);

            upload.Status = UploadStatus.Complete;

            // File is fully uploaded, don't let the user cancel this request
            await _context.SaveChangesAsync();

            return
                (new JsonResult(
                     new
            {
                id = upload.Id,
                path = Url.Page("/Upload", values: new { id = upload.Id }),
                url = Url.PageLink("/Upload", values: new { id = upload.Id }),
                delete = Url.ActionLink("DeleteUpload", values: new { id = upload.Id }),
                raw = Url.ActionLink("Raw", values: new { id = upload.Id }),
                download = Url.ActionLink("Download", values: new { id = upload.Id })
            }));
        }
示例#3
0
        private async Task <IActionResult> GetFile(string id, string contentDispositionType)
        {
            if (string.IsNullOrWhiteSpace(id))
            {
                return(NotFound());
            }

            var upload = await _context.Uploads
                         .FirstOrDefaultAsync(x => x.Id == id && !x.PendingForDeletionAt.HasValue, Request.HttpContext.RequestAborted);

            if (upload == null)
            {
                return(NotFound());
            }

            var range = Request.GetTypedHeaders().Range;

            var result = await _store.DownloadAsync(upload, range, Request.HttpContext.RequestAborted);

            if (result.ContentRange != null)
            {
                Response.StatusCode = (int)HttpStatusCode.PartialContent;
                Response.Headers.Add("Accept-Ranges", "bytes");
                Response.Headers.Add("Content-Range", result.ContentRange);
            }

            Response.Headers.Add("Content-Disposition", $"{contentDispositionType};filename={upload.Name + upload.Extension}");

            if (MediaTypeHelpers.ParseMediaType(upload.MediaType) == MediaType.Text)
            {
                return(File(result.Stream, "text/plain", true));
            }
            else
            {
                return(File(result.Stream, upload.MediaType, true));
            }
        }
示例#4
0
    private async Task InvokeInternal(HttpContext context)
    {
        var options = _options.CurrentValue;
        RequestBufferingStream?requestBufferingStream = null;
        Stream?originalBody = null;

        if ((HttpLoggingFields.Request & options.LoggingFields) != HttpLoggingFields.None)
        {
            var request = context.Request;
            var list    = new List <KeyValuePair <string, object?> >(
                request.Headers.Count + DefaultRequestFieldsMinusHeaders);

            if (options.LoggingFields.HasFlag(HttpLoggingFields.RequestProtocol))
            {
                AddToList(list, nameof(request.Protocol), request.Protocol);
            }

            if (options.LoggingFields.HasFlag(HttpLoggingFields.RequestMethod))
            {
                AddToList(list, nameof(request.Method), request.Method);
            }

            if (options.LoggingFields.HasFlag(HttpLoggingFields.RequestScheme))
            {
                AddToList(list, nameof(request.Scheme), request.Scheme);
            }

            if (options.LoggingFields.HasFlag(HttpLoggingFields.RequestPath))
            {
                AddToList(list, nameof(request.PathBase), request.PathBase);
                AddToList(list, nameof(request.Path), request.Path);
            }

            if (options.LoggingFields.HasFlag(HttpLoggingFields.RequestQuery))
            {
                AddToList(list, nameof(request.QueryString), request.QueryString.Value);
            }

            if (options.LoggingFields.HasFlag(HttpLoggingFields.RequestHeaders))
            {
                FilterHeaders(list, request.Headers, options._internalRequestHeaders);
            }

            if (options.LoggingFields.HasFlag(HttpLoggingFields.RequestBody))
            {
                if (MediaTypeHelpers.TryGetEncodingForMediaType(request.ContentType,
                                                                options.MediaTypeOptions.MediaTypeStates,
                                                                out var encoding))
                {
                    originalBody           = request.Body;
                    requestBufferingStream = new RequestBufferingStream(
                        request.Body,
                        options.RequestBodyLogLimit,
                        _logger,
                        encoding);
                    request.Body = requestBufferingStream;
                }
                else
                {
                    _logger.UnrecognizedMediaType();
                }
            }

            var httpRequestLog = new HttpRequestLog(list);

            _logger.RequestLog(httpRequestLog);
        }

        ResponseBufferingStream? responseBufferingStream = null;
        IHttpResponseBodyFeature?originalBodyFeature     = null;

        try
        {
            var response = context.Response;

            if (options.LoggingFields.HasFlag(HttpLoggingFields.ResponseBody))
            {
                originalBodyFeature = context.Features.Get <IHttpResponseBodyFeature>() !;

                // TODO pool these.
                responseBufferingStream = new ResponseBufferingStream(originalBodyFeature,
                                                                      options.ResponseBodyLogLimit,
                                                                      _logger,
                                                                      context,
                                                                      options.MediaTypeOptions.MediaTypeStates,
                                                                      options);
                response.Body = responseBufferingStream;
                context.Features.Set <IHttpResponseBodyFeature>(responseBufferingStream);
            }

            await _next(context);

            if (requestBufferingStream?.HasLogged == false)
            {
                // If the middleware pipeline didn't read until 0 was returned from readasync,
                // make sure we log the request body.
                requestBufferingStream.LogRequestBody();
            }

            if (responseBufferingStream == null || responseBufferingStream.FirstWrite == false)
            {
                // No body, write headers here.
                LogResponseHeaders(response, options, _logger);
            }

            if (responseBufferingStream != null)
            {
                var responseBody = responseBufferingStream.GetString(responseBufferingStream.Encoding);
                if (!string.IsNullOrEmpty(responseBody))
                {
                    _logger.ResponseBody(responseBody);
                }
            }
        }
        finally
        {
            responseBufferingStream?.Dispose();

            if (originalBodyFeature != null)
            {
                context.Features.Set(originalBodyFeature);
            }

            requestBufferingStream?.Dispose();

            if (originalBody != null)
            {
                context.Request.Body = originalBody;
            }
        }
    }
示例#5
0
        private Func <IServiceProvider, DefaultTusConfiguration> CreateTusConfiguration(StorageType storageType)
        => (serviceProvider) =>
        {
            var logger = serviceProvider.GetService <ILoggerFactory>().CreateLogger <Startup>();

            return(new DefaultTusConfiguration
            {
                Store = new HoneydewTusStore(serviceProvider),
                UrlPath = "/api/tusupload",
                MetadataParsingStrategy = MetadataParsingStrategy.AllowEmptyValues,
                Events = new Events
                {
                    OnAuthorizeAsync = ctx =>
                    {
                        if (!ctx.HttpContext.User.Identity.IsAuthenticated)
                        {
                            ctx.FailRequest(HttpStatusCode.Unauthorized);
                        }

                        return Task.CompletedTask;
                    },
                    OnBeforeCreateAsync = ctx =>
                    {
                        // Partial files are not complete so we do not need to validate
                        // the metadata in our example.
                        if (ctx.FileConcatenation is FileConcatPartial)
                        {
                            return Task.CompletedTask;
                        }

                        if (!ctx.Metadata.ContainsKey("name") || ctx.Metadata["name"].HasEmptyValue || string.IsNullOrWhiteSpace(ctx.Metadata["name"].GetString(Encoding.UTF8)))
                        {
                            ctx.FailRequest("name metadata must be specified.");
                        }

                        return Task.CompletedTask;
                    },
                    OnCreateCompleteAsync = async ctx =>
                    {
                        logger.LogInformation($"Created file {ctx.FileId} using {ctx.Store.GetType().FullName}");

                        var name = ctx.Metadata["name"].GetString(Encoding.UTF8);
                        var mediaType = MediaTypeHelpers.GetMediaTypeFromMetadata(ctx.Metadata);

                        var filename = Path.GetFileNameWithoutExtension(name);
                        var extension = Path.GetExtension(name);

                        var scope = serviceProvider.CreateScope();

                        var userManager =
                            scope
                            .ServiceProvider
                            .GetService <UserManager <User> >();

                        await using var context =
                                        scope
                                        .ServiceProvider
                                        .GetService <ApplicationDbContext>();

                        await context.Uploads.AddAsync(
                            new Upload
                        {
                            Id = ctx.FileId,
                            Name = filename,
                            Extension = extension,
                            OriginalFileNameWithExtension = Path.GetFileName(name),
                            MediaType = mediaType,
                            CodeLanguage = CodeLanguageHelpers.GetLanageFromExtension(extension),
                            Length = ctx.UploadLength,
                            Metadata = ctx.HttpContext.Request.Headers[HeaderConstants.UploadMetadata],
                            UserId = userManager.GetUserId(ctx.HttpContext.User),
                            CreatedBy = userManager.GetUserName(ctx.HttpContext.User)
                        }, ctx.CancellationToken);

                        await context.SaveChangesAsync(ctx.CancellationToken);
                    },
                    OnBeforeDeleteAsync = ctx =>
                    {
                        // Can the file be deleted? If not call ctx.FailRequest(<message>);
                        return Task.CompletedTask;
                    },
                    OnDeleteCompleteAsync = ctx =>
                    {
                        logger.LogInformation($"Deleted file {ctx.FileId} using {ctx.Store.GetType().FullName}");
                        return Task.CompletedTask;
                    },
                    OnFileCompleteAsync = async ctx =>
                    {
                        logger.LogInformation($"Upload of {ctx.FileId} completed using {ctx.Store.GetType().FullName}");

                        await using var context =
                                        serviceProvider
                                        .CreateScope()
                                        .ServiceProvider
                                        .GetService <ApplicationDbContext>();

                        var upload = await context.Uploads.FindAsync(ctx.FileId);

                        upload.Status = UploadStatus.Complete;

                        // Don't want the user to be able to cancel
                        await context.SaveChangesAsync();
                    }
                },