示例#1
0
        /// <summary>
        /// Creates a new database with the given name in the server.
        /// The name must begin with a lowercase letter and can contains only lowercase characters, digits or _, $, (, ), +, - and /.s
        /// </summary>
        /// <typeparam name="TSource">The type of database documents.</typeparam>
        /// <param name="database">The database name.</param>
        /// <param name="shards">The number of range partitions. Default is 8, unless overridden in the cluster config.</param>
        /// <param name="replicas">The number of copies of the database in the cluster. The default is 3, unless overridden in the cluster config.</param>
        /// <returns>A task that represents the asynchronous operation. The task result contains the newly created CouchDB database.</returns>
        public async Task <CouchDatabase <TSource> > CreateDatabaseAsync <TSource>(string database, int?shards = null, int?replicas = null) where TSource : CouchDocument
        {
            database = EscapeDatabaseName(database);

            IFlurlRequest request = NewRequest()
                                    .AppendPathSegment(database);

            if (shards.HasValue)
            {
                request = request.SetQueryParam("q", shards.Value);
            }

            if (replicas.HasValue)
            {
                request = request.SetQueryParam("n", replicas.Value);
            }

            OperationResult result = await request
                                     .PutAsync(null)
                                     .ReceiveJson <OperationResult>()
                                     .SendRequestAsync()
                                     .ConfigureAwait(false);

            if (!result.Ok)
            {
                throw new CouchException("Something went wrong during the creation");
            }

            return(new CouchDatabase <TSource>(_flurlClient, _settings, ConnectionString, database));
        }
示例#2
0
        /// <summary>
        /// Creates a new database with the given name in the server.
        /// The name must begin with a lowercase letter and can contains only lowercase characters, digits or _, $, (, ), +, - and /.s
        /// </summary>
        /// <typeparam name="TSource">The type of database documents.</typeparam>
        /// <param name="database">The database name.</param>
        /// <param name="shards">The number of range partitions. Default is 8, unless overridden in the cluster config.</param>
        /// <param name="replicas">The number of copies of the database in the cluster. The default is 3, unless overridden in the cluster config.</param>
        /// <returns>A task that represents the asynchronous operation. The task result contains the newly created CouchDB database.</returns>
        public async Task <CouchDatabase <TSource> > CreateDatabaseAsync <TSource>(string database, int?shards = null, int?replicas = null) where TSource : CouchDocument
        {
            if (database == null)
            {
                throw new ArgumentNullException(nameof(database));
            }

            if (!_systemDatabases.Contains(database) && !new Regex(@"^[a-z][a-z0-9_$()+/-]*$").IsMatch(database))
            {
                throw new ArgumentException($"Name {database} contains invalid characters. Please visit: https://docs.couchdb.org/en/stable/api/database/common.html#put--db", nameof(database));
            }

            IFlurlRequest request = NewRequest()
                                    .AppendPathSegment(database);

            if (shards.HasValue)
            {
                request = request.SetQueryParam("q", shards.Value);
            }
            if (replicas.HasValue)
            {
                request = request.SetQueryParam("n", replicas.Value);
            }

            OperationResult result = await request
                                     .PutAsync(null)
                                     .ReceiveJson <OperationResult>()
                                     .SendRequestAsync()
                                     .ConfigureAwait(false);

            if (!result.Ok)
            {
                throw new CouchException("Something went wrong during the creation");
            }

            return(new CouchDatabase <TSource>(_flurlClient, _settings, ConnectionString, database));
        }
示例#3
0
        private async Task <Response> ProxyRequest(NancyContext context, CancellationToken cancellationToken)
        {
            string path   = context.Request.Path;
            string method = context.Request.Method.ToUpperInvariant();

            if (!path.StartsWith("/nfsw/Engine.svc"))
            {
                throw new ProxyException("Invalid request path: " + path);
            }

            path = path.Substring("/nfsw/Engine.svc".Length);

            Url resolvedUrl = new Url(ServerProxy.Instance.GetServerUrl()).AppendPathSegment(path);

            foreach (var queryParamName in context.Request.Query)
            {
                resolvedUrl = resolvedUrl.SetQueryParam(queryParamName, context.Request.Query[queryParamName],
                                                        NullValueHandling.Ignore);
            }

            IFlurlRequest request = resolvedUrl.AllowAnyHttpStatus();

            foreach (var header in context.Request.Headers)
            {
                request = request.WithHeader(header.Key,
                                             header.Key == "Host" ? resolvedUrl.ToUri().Host : header.Value.First());
            }

            var requestBody = context.Request.Method != "GET" ? context.Request.Body.AsString(Encoding.UTF8) : "";

            CommunicationLog.RecordEntry(ServerProxy.Instance.GetServerName(), "SERVER",
                                         CommunicationLogEntryType.Request,
                                         new CommunicationLogRequest(requestBody, resolvedUrl.ToString(), method));

            HttpResponseMessage responseMessage;

            var POSTContent = String.Empty;

            var queryParams = new Dictionary <string, object>();

            foreach (var param in context.Request.Query)
            {
                var value = context.Request.Query[param];
                queryParams[param] = value;
            }

            var GETContent = string.Join(";", queryParams.Select(x => x.Key + "=" + x.Value).ToArray());

            // ReSharper disable once LocalizableElement
            //Console.WriteLine($"[LOG] [{method}] ProxyHandler: {path}");

            switch (method)
            {
            case "GET":
                responseMessage = await request.GetAsync(cancellationToken);

                break;

            case "POST":
                responseMessage = await request.PostAsync(new CapturedStringContent(requestBody, Encoding.UTF8),
                                                          cancellationToken);

                POSTContent = context.Request.Body.AsString();
                break;

            case "PUT":
                responseMessage = await request.PutAsync(new CapturedStringContent(requestBody, Encoding.UTF8),
                                                         cancellationToken);

                break;

            case "DELETE":
                responseMessage = await request.DeleteAsync(cancellationToken);

                break;

            default:
                throw new ProxyException("Cannot handle request method: " + method);
            }

            var responseBody = await responseMessage.Content.ReadAsStringAsync();

            if (path == "/User/GetPermanentSession")
            {
                responseBody = Self.CleanFromUnknownChars(responseBody);
            }

            int statusCode = (int)responseMessage.StatusCode;

            try
            {
                DiscordGamePresence.HandleGameState(path, responseBody, POSTContent, GETContent);
            }
            catch (Exception e)
            {
                Log.Error($"DISCORD RPC ERROR [handling {context.Request.Path}]");
                Log.Error($"\tMESSAGE: {e.Message}");
                Log.Error($"\t{e.StackTrace}");
                await Self.SubmitError(e);
            }

            TextResponse textResponse = new TextResponse(responseBody,
                                                         responseMessage.Content.Headers.ContentType?.MediaType ?? "application/xml;charset=UTF-8")
            {
                StatusCode = (HttpStatusCode)statusCode
            };

            queryParams.Clear();

            CommunicationLog.RecordEntry(ServerProxy.Instance.GetServerName(), "SERVER",
                                         CommunicationLogEntryType.Response, new CommunicationLogResponse(
                                             responseBody, resolvedUrl.ToString(), method));

            return(textResponse);
        }
示例#4
0
 protected override Task <IFlurlResponse> CallOnFlurlRequest(IFlurlRequest req) => req.PutAsync(null);
示例#5
0
        private async Task <Response> ProxyRequest(NancyContext ctx, CancellationToken ct)
        {
            Debug.WriteLine("{0} - {1}", ctx.Request.Method, ctx.Request.Path);

            foreach (var requestHeader in ctx.Request.Headers)
            {
                Debug.WriteLine("\t{0}: {1}", requestHeader.Key, string.Join(" ; ", requestHeader.Value));
            }

            // Build new request
            var url = new Flurl.Url(ServerProxy.Instance.GetCurrentServer().ServerAddress)
                      .AppendPathSegment(ctx.Request.Path.Replace("/nfsw/Engine.svc", ""));

            foreach (var key in ctx.Request.Query)
            {
                url = url.SetQueryParam(key, ctx.Request.Query[key], NullValueHandling.Ignore);
            }

            IFlurlRequest request = url.WithTimeout(TimeSpan.FromSeconds(30));

            foreach (var requestHeader in ctx.Request.Headers)
            {
                request = request.WithHeader(requestHeader.Key, requestHeader.Value.First());
            }

            HttpResponseMessage responseMessage;

            switch (ctx.Request.Method)
            {
            case "GET":
                responseMessage = await request.GetAsync(ct);

                break;

            case "POST":
                responseMessage =
                    await request.PostAsync(new CapturedStringContent(ctx.Request.Body.AsString(Encoding.UTF8)), ct);

                break;

            case "PUT":
                responseMessage =
                    await request.PutAsync(new CapturedStringContent(ctx.Request.Body.AsString(Encoding.UTF8)), ct);

                break;

            case "DELETE":
                responseMessage =
                    await request.DeleteAsync(ct);

                break;

            default:
                throw new ServerProxyException("Cannot handle request method: " + ctx.Request.Method);
            }

            return(new TextResponse(await responseMessage.Content.ReadAsStringAsync(),
                                    responseMessage.Content.Headers.ContentType?.MediaType ?? "application/xml;charset=UTF-8")
            {
                StatusCode = (HttpStatusCode)(int)responseMessage.StatusCode
            });
        }
示例#6
0
        private async Task <Response> ProxyRequest(NancyContext context, CancellationToken cancellationToken)
        {
            string path   = Strings.Encode(context.Request.Path);
            string method = Strings.Encode(context.Request.Method.ToUpperInvariant());

            if (!path.StartsWith("/nfsw/Engine.svc"))
            {
                Log.Error("PROXY HANDLER: Invalid Request: " + path);
                return("SBRW Launcher Version: " + Theming.PrivacyRPCBuild + "\nBuild Date: " + InsiderInfo.BuildNumberOnly());
            }
            else
            {
                path = path.Substring("/nfsw/Engine.svc".Length);

                UrlFlurl resolvedUrl = new UrlFlurl(ServerProxy.Instance.GetServerUrl()).AppendPathSegment(path, false);

                foreach (var queryParamName in context.Request.Query)
                {
                    resolvedUrl = resolvedUrl.SetQueryParam(queryParamName, context.Request.Query[queryParamName],
                                                            NullValueHandling.Ignore);
                }

                IFlurlRequest request = resolvedUrl.AllowAnyHttpStatus();

                foreach (var header in context.Request.Headers)
                {
                    /* Don't send Content-Length for GET requests - HeyItsLeo */
                    if (method == "GET" && header.Key.ToLowerInvariant() == "content-length")
                    {
                        continue;
                    }

                    request = request.WithHeader
                                  (header.Key, (header.Key == "Host") ? resolvedUrl.ToUri().Host : ((header.Value != null) ? header.Value.First() : string.Empty));
                }

                string requestBody = (method != "GET") ? context.Request.Body.AsString(UTF8) : string.Empty;

                CommunicationLog.RecordEntry(ServerProxy.Instance.GetServerName(), "SERVER", CommunicationLogEntryType.Request,
                                             new CommunicationLogRequest(requestBody, resolvedUrl.ToString(), method));

                IFlurlResponse responseMessage;

                if (path == "/event/arbitration" && !string.IsNullOrWhiteSpace(requestBody))
                {
                    requestBody = Strings.Encode(
                        requestBody.Replace("</TopSpeed>", "</TopSpeed><Konami>" + AntiCheat.Get_Cheat_Status() + "</Konami>"));
                    foreach (var header in context.Request.Headers)
                    {
                        if (header.Key.ToLowerInvariant() == "content-length")
                        {
                            int KonamiCode = Convert.ToInt32(header.Value.First()) +
                                             ("<Konami>" + AntiCheat.Get_Cheat_Status() + "</Konami>").Length;
                            request = request.WithHeader(header.Key, KonamiCode);
                        }
                    }
                }

                switch (method)
                {
                case "GET":
                    responseMessage = await request.GetAsync(cancellationToken);

                    break;

                case "POST":
                    responseMessage = await request.PostAsync(new CapturedStringContent(requestBody),
                                                              cancellationToken);

                    break;

                case "PUT":
                    responseMessage = await request.PutAsync(new CapturedStringContent(requestBody),
                                                             cancellationToken);

                    break;

                case "DELETE":
                    responseMessage = await request.DeleteAsync(cancellationToken);

                    break;

                default:
                    Log.Error("PROXY HANDLER: Cannot handle Request Method " + method);
                    responseMessage = null;
                    break;
                }

                string responseBody = Strings.Encode(await responseMessage.GetStringAsync());

                int statusCode = responseMessage.StatusCode;

                DiscordGamePresence.HandleGameState(path, responseBody, context.Request.Query);

                TextResponse Response = new TextResponse(responseBody,
                                                         responseMessage.ResponseMessage.Content.Headers.ContentType?.MediaType ?? "application/xml;charset=UTF-8")
                {
                    StatusCode = (HttpStatusCode)statusCode
                };

                CommunicationLog.RecordEntry(ServerProxy.Instance.GetServerName(), "SERVER", CommunicationLogEntryType.Response,
                                             new CommunicationLogResponse(responseBody, resolvedUrl.ToString(), method));

                return(Response);
            }
        }