/// <summary> /// Executes the PUT method on the resource. /// </summary> /// <param name="Request">HTTP Request</param> /// <param name="Response">HTTP Response</param> /// <exception cref="HttpException">If an error occurred when processing the method.</exception> public async Task PUT(HttpRequest Request, HttpResponse Response) { string FullPath = this.GetFullPath(Request); if (!Request.HasData) { throw new BadRequestException(); } string Folder = Path.GetDirectoryName(FullPath); if (!Directory.Exists(Folder)) { Directory.CreateDirectory(Folder); } using (FileStream f = File.Create(FullPath)) { Request.DataStream.CopyTo(f); } Response.StatusCode = 201; await Response.SendResponse(); Response.Dispose(); }
private async Task RaiseFileNotFound(string FullPath, HttpRequest Request, HttpResponse Response) { NotFoundException ex = new NotFoundException("File not found: " + FullPath.Substring(this.folderPath.Length)); FileNotFoundEventHandler h = this.FileNotFound; if (!(h is null)) { FileNotFoundEventArgs e = new FileNotFoundEventArgs(ex, FullPath, Request, Response); try { h(this, e); } catch (Exception ex2) { Log.Critical(ex2); } ex = e.Exception; if (ex is null) { return; // Sent asynchronously from event handler. } } Log.Warning("File not found.", FullPath, Request.RemoteEndPoint, "FileNotFound"); await Response.SendResponse(ex); Response.Dispose(); }
/// <summary> /// Executes the ranged PUT method on the resource. /// </summary> /// <param name="Request">HTTP Request</param> /// <param name="Response">HTTP Response</param> /// <param name="Interval">Content byte range.</param> /// <exception cref="HttpException">If an error occurred when processing the method.</exception> public async Task PUT(HttpRequest Request, HttpResponse Response, ContentByteRangeInterval Interval) { string FullPath = this.GetFullPath(Request); if (!Request.HasData) { throw new BadRequestException(); } string Folder = Path.GetDirectoryName(FullPath); if (!Directory.Exists(Folder)) { Directory.CreateDirectory(Folder); } using (FileStream f = File.Exists(FullPath) ? File.OpenWrite(FullPath) : File.Create(FullPath)) { long l; if ((l = Interval.First - f.Length) > 0) { f.Position = f.Length; int BlockSize = (int)Math.Min(BufferSize, Interval.First - f.Length); byte[] Block = new byte[BlockSize]; int i; while (l > 0) { i = (int)Math.Min(l, BlockSize); f.Write(Block, 0, i); l -= i; } } else { f.Position = Interval.First; } Request.DataStream.CopyTo(f); } Response.StatusCode = 201; await Response.SendResponse(); Response.Dispose(); }
/// <summary> /// Executes the DELETE method on the resource. /// </summary> /// <param name="Request">HTTP Request</param> /// <param name="Response">HTTP Response</param> /// <exception cref="HttpException">If an error occurred when processing the method.</exception> public void DELETE(HttpRequest Request, HttpResponse Response) { string FullPath = this.GetFullPath(Request); if (File.Exists(FullPath)) { File.Delete(FullPath); } else if (Directory.Exists(FullPath)) { Directory.Delete(FullPath, true); } else { throw new NotFoundException("File not found: " + FullPath.Substring(this.folderPath.Length)); } Response.SendResponse(); Response.Dispose(); }
/// <summary> /// Executes the DELETE method on the resource. /// </summary> /// <param name="Request">HTTP Request</param> /// <param name="Response">HTTP Response</param> /// <exception cref="HttpException">If an error occurred when processing the method.</exception> public async Task DELETE(HttpRequest Request, HttpResponse Response) { string FullPath = this.GetFullPath(Request); if (File.Exists(FullPath)) { File.Delete(FullPath); } else if (Directory.Exists(FullPath)) { Directory.Delete(FullPath, true); } else { throw new NotFoundException("File not found: " + Request.SubPath); } await Response.SendResponse(); Response.Dispose(); }
/// <summary> /// Executes a method on the resource. The default behaviour is to call the corresponding execution methods defined in the specialized /// interfaces <see cref="IHttpGetMethod"/>, <see cref="IHttpPostMethod"/>, <see cref="IHttpPutMethod"/> and <see cref="IHttpDeleteMethod"/> /// if they are defined for the resource. /// </summary> /// <param name="Server">HTTP Server</param> /// <param name="Request">HTTP Request</param> /// <param name="Response">HTTP Response</param> /// <exception cref="HttpException">If an error occurred when processing the method.</exception> public virtual void Execute(HttpServer Server, HttpRequest Request, HttpResponse Response) { HttpRequestHeader Header = Request.Header; string Method = Request.Header.Method; if (this.UserSessions) { HttpFieldCookie Cookie; string HttpSessionID; if ((Cookie = Request.Header.Cookie) is null || string.IsNullOrEmpty(HttpSessionID = Cookie["HttpSessionID"])) { HttpSessionID = System.Convert.ToBase64String(Hashes.ComputeSHA512Hash(Guid.NewGuid().ToByteArray())); Response.SetCookie(new HTTP.Cookie("HttpSessionID", HttpSessionID, null, "/", null, false, true)); } Request.Session = Server.GetSession(HttpSessionID); } switch (Method) { case "GET": case "HEAD": if (this.getRanges != null) { Response.SetHeader("Accept-Ranges", "bytes"); if (Header.Range != null) { ByteRangeInterval FirstInterval = Header.Range.FirstInterval; if (FirstInterval is null) { throw new RangeNotSatisfiableException(); } else { Response.OnlyHeader = Method == "HEAD"; Response.StatusCode = 206; Response.StatusMessage = "Partial Content"; this.getRanges.GET(Request, Response, FirstInterval); } } else { Response.OnlyHeader = Method == "HEAD"; if (this.get != null) { this.get.GET(Request, Response); } else { this.getRanges.GET(Request, Response, new ByteRangeInterval(0, null)); } } } else if (this.get != null) { Response.OnlyHeader = Method == "HEAD"; this.get.GET(Request, Response); } else { throw new MethodNotAllowedException(this.allowedMethods); } break; case "POST": if (this.postRanges != null) { if (Header.ContentRange != null) { ContentByteRangeInterval Interval = Header.ContentRange.Interval; if (Interval is null) { throw new RangeNotSatisfiableException(); } else { this.postRanges.POST(Request, Response, Interval); } } else { if (this.post != null) { this.post.POST(Request, Response); } else { long Total; if (Header.ContentLength != null) { Total = Header.ContentLength.ContentLength; } else if (Request.DataStream != null) { Total = Request.DataStream.Position; } else { Total = 0; } this.postRanges.POST(Request, Response, new ContentByteRangeInterval(0, Total - 1, Total)); } } } else if (this.post != null) { this.post.POST(Request, Response); } else { throw new MethodNotAllowedException(this.allowedMethods); } break; case "PUT": if (this.putRanges != null) { if (Header.ContentRange != null) { ContentByteRangeInterval Interval = Header.ContentRange.Interval; if (Interval is null) { throw new RangeNotSatisfiableException(); } else { this.putRanges.PUT(Request, Response, Interval); } } else { if (this.put != null) { this.put.PUT(Request, Response); } else { long Total; if (Header.ContentLength != null) { Total = Header.ContentLength.ContentLength; } else if (Request.DataStream != null) { Total = Request.DataStream.Position; } else { Total = 0; } this.putRanges.PUT(Request, Response, new ContentByteRangeInterval(0, Total - 1, Total)); } } } else if (this.put != null) { this.put.PUT(Request, Response); } else { throw new MethodNotAllowedException(this.allowedMethods); } break; case "DELETE": if (this.delete is null) { throw new MethodNotAllowedException(this.allowedMethods); } else { this.delete.DELETE(Request, Response); } break; case "OPTIONS": if (this.options is null) { throw new MethodNotAllowedException(this.allowedMethods); } else { this.options.OPTIONS(Request, Response); } break; case "TRACE": if (this.trace is null) { throw new MethodNotAllowedException(this.allowedMethods); } else { this.trace.TRACE(Request, Response); } break; default: throw new MethodNotAllowedException(this.allowedMethods); } if (this.Synchronous) { Response.SendResponse(); Response.Dispose(); } }