/// <summary> /// Executes a <see cref="RestCommand"/> using the provided verbs, parameters, request, and context objects /// </summary> /// <param name="cmd">The REST command to execute</param> /// <param name="verbs">The REST verbs used in the command</param> /// <param name="parms">The REST parameters used in the command</param> /// <param name="request">The HTTP request object associated with the command</param> /// <param name="context">The HTTP context associated with the command</param> /// <returns></returns> protected virtual object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms, IRequest request, IHttpContext context) { object result = cmd.Execute(verbs, parms, request, context); if (cmd.DoLog && Restful.Instance.Config.LogConnections) { TShock.Log.ConsoleInfo("Anonymous requested REST endpoint: " + BuildRequestUri(cmd, verbs, parms, false)); } return(result); }
public object Execute(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData, IRequest request, IHttpContext context) { if (tokenData.Equals(SecureRest.TokenData.None)) { return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." } } ; return(callback(new RestRequestArgs(verbs, parameters, request, tokenData, context))); } }
/// <summary> /// Builds a request URI from the parameters, verbs, and URI template of a <see cref="RestCommand"/> /// </summary> /// <param name="cmd">The REST command to take the URI template from</param> /// <param name="verbs">Verbs used in building the URI string</param> /// <param name="parms">Parameters used in building the URI string</param> /// <param name="includeToken">Whether or not to include a token in the URI</param> /// <returns></returns> protected virtual string BuildRequestUri( RestCommand cmd, RestVerbs verbs, IParameterCollection parms, bool includeToken = true ) { StringBuilder requestBuilder = new StringBuilder(cmd.UriTemplate); char separator = '?'; foreach (IParameter paramImpl in parms) { Parameter param = (paramImpl as Parameter); if (param == null || (!includeToken && param.Name.Equals("token", StringComparison.InvariantCultureIgnoreCase))) { continue; } requestBuilder.Append(separator); requestBuilder.Append(param.Name); requestBuilder.Append('='); requestBuilder.Append(param.Value); separator = '&'; } return(requestBuilder.ToString()); }
/// <summary> /// Attempts to process a request received by the <see cref="HttpListener"/> /// </summary> /// <param name="sender">Sender of the request</param> /// <param name="e">RequestEventArgs received</param> /// <returns>A <see cref="RestObject"/> describing the state of the request</returns> protected virtual object ProcessRequest(object sender, RequestEventArgs e) { try { var uri = e.Request.Uri.AbsolutePath; uri = uri.TrimEnd('/'); string upgrade = null; if (redirects.ContainsKey(uri)) { upgrade = redirects[uri].Item2; uri = redirects[uri].Item1; } foreach (var com in commands) { var verbs = new RestVerbs(); if (com.HasVerbs) { var match = Regex.Match(uri, com.UriVerbMatch); if (!match.Success) { continue; } if ((match.Groups.Count - 1) != com.UriVerbs.Length) { continue; } for (int i = 0; i < com.UriVerbs.Length; i++) { verbs.Add(com.UriVerbs[i], match.Groups[i + 1].Value); } } else if (com.UriTemplate.ToLower() != uri.ToLower()) { continue; } var obj = ExecuteCommand(com, verbs, e.Request.Parameters, e.Request, e.Context); if (obj != null) { if (!String.IsNullOrWhiteSpace(upgrade) && obj is RestObject) { if (!(obj as RestObject).ContainsKey("upgrade")) { (obj as RestObject).Add("upgrade", upgrade); } } return(obj); } } } catch (Exception exception) { return(new RestObject("500") { { "error", "Internal server error." }, { "errormsg", exception.Message }, { "stacktrace", exception.StackTrace }, }); } return(new RestObject("404") { { "error", "Specified API endpoint doesn't exist. Refer to the documentation for a list of valid endpoints." } }); }
public virtual object Execute(RestVerbs verbs, IParameterCollection parameters, IRequest request, IHttpContext context) { return(callback(new RestRequestArgs(verbs, parameters, request, context))); }
protected override object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms, IRequest request, IHttpContext context) { if (!cmd.RequiresToken) { return(base.ExecuteCommand(cmd, verbs, parms, request, context)); } var token = parms["token"]; if (token == null) { return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." } } ; SecureRestCommand secureCmd = (SecureRestCommand)cmd; TokenData tokenData; if (!Tokens.TryGetValue(token, out tokenData) && !AppTokens.TryGetValue(token, out tokenData)) { return new RestObject("403") { Error = "Not authorized. The specified API endpoint requires a token, but the provided token was not valid." } } ; Group userGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName); if (userGroup == null) { Tokens.Remove(token); return(new RestObject("403") { Error = "Not authorized. The provided token became invalid due to group changes, please create a new token." }); } if (secureCmd.Permissions.Length > 0 && secureCmd.Permissions.All(perm => !userGroup.HasPermission(perm))) { return(new RestObject("403") { Error = string.Format("Not authorized. User \"{0}\" has no access to use the specified API endpoint.", tokenData.Username) }); } //Main.rand being null can cause issues in command execution. //This should solve that if (Main.rand == null) { Main.rand = new Terraria.Utilities.UnifiedRandom(); } object result = secureCmd.Execute(verbs, parms, tokenData, request, context); if (cmd.DoLog && TShock.Config.LogRest) { TShock.Utils.SendLogs(string.Format( "\"{0}\" requested REST endpoint: {1}", tokenData.Username, this.BuildRequestUri(cmd, verbs, parms, false)), Color.PaleVioletRed); } return(result); } } }