Beispiel #1
0
        private async Task <HttpResponseMessage> PushDeployAsync(
            ZipDeploymentInfo deploymentInfo,
            bool isAsync)
        {
            var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip");
            var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName);

            using (_tracer.Step("Writing content to {0}", zipFilePath))
            {
                using (var file = FileSystemHelpers.CreateFile(zipFilePath))
                {
                    await Request.Content.CopyToAsync(file);
                }
            }

            deploymentInfo.RepositoryUrl = zipFilePath;

            var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD");

            var response = Request.CreateResponse();

            switch (result)
            {
            case FetchDeploymentRequestResult.RunningAynschronously:
                if (isAsync)
                {
                    // latest deployment keyword reserved to poll till deployment done
                    response.Headers.Location = new Uri(UriHelper.GetRequestUri(Request),
                                                        String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                }
                response.StatusCode = HttpStatusCode.Accepted;
                break;

            case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                // Should never hit this for zip push deploy
                response.StatusCode = HttpStatusCode.Forbidden;
                _tracer.Trace("Scm is not enabled, reject all requests.");
                break;

            case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_AutoSwapDeploymentOngoing);
                break;

            case FetchDeploymentRequestResult.Pending:
                // Shouldn't happen here, as we disallow deferral for this use case
                response.StatusCode = HttpStatusCode.Accepted;
                break;

            case FetchDeploymentRequestResult.RanSynchronously:
                response.StatusCode = HttpStatusCode.OK;
                break;

            case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_DeploymentInProgress);
                break;

            default:
                response.StatusCode = HttpStatusCode.BadRequest;
                break;
            }

            return(response);
        }
        private async Task <HttpResponseMessage> PushDeployAsync(ZipDeploymentInfo deploymentInfo, bool isAsync)
        {
            var content       = Request.Content;
            var isRequestJSON = content.Headers?.ContentType?.MediaType?.Equals("application/json", StringComparison.OrdinalIgnoreCase);

            if (isRequestJSON == true)
            {
                try
                {
                    var requestObject = await Request.Content.ReadAsAsync <JObject>();

                    deploymentInfo.ZipURL = ArmUtils.IsArmRequest(Request) ? GetZipURLFromARMJSON(requestObject) : GetZipURLFromJSON(requestObject);
                }
                catch (Exception ex)
                {
                    return(ArmUtils.CreateErrorResponse(Request, HttpStatusCode.BadRequest, ex));
                }
            }
            else
            {
                if (_settings.RunFromLocalZip())
                {
                    await WriteSitePackageZip(deploymentInfo, _tracer, Request.Content);
                }
                else
                {
                    var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip");
                    var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName);

                    using (_tracer.Step("Saving request content to {0}", zipFilePath))
                    {
                        await content.CopyToAsync(zipFilePath, _tracer);
                    }

                    deploymentInfo.RepositoryUrl = zipFilePath;
                }
            }

            isAsync = ArmUtils.IsArmRequest(Request) ? true : isAsync;

            var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD");

            var response = Request.CreateResponse();

            switch (result)
            {
            case FetchDeploymentRequestResult.RunningAynschronously:
                if (ArmUtils.IsArmRequest(Request))
                {
                    DeployResult deployResult = new DeployResult();
                    response = Request.CreateResponse(HttpStatusCode.Accepted, ArmUtils.AddEnvelopeOnArmRequest(deployResult, Request));
                    string statusURL = GetStatusUrl();
                    // Should not happen: If we couldn't make the URL, there must have been an error in the request
                    if (string.IsNullOrEmpty(statusURL))
                    {
                        var badResponse = Request.CreateResponse();
                        badResponse.StatusCode = HttpStatusCode.BadRequest;
                        return(badResponse);
                    }
                    // latest deployment keyword reserved to poll till deployment done
                    response.Headers.Location = new Uri(statusURL +
                                                        String.Format("/deployments/{0}?api-version=2018-02-01&deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                }
                else if (isAsync)
                {
                    // latest deployment keyword reserved to poll till deployment done
                    response.Headers.Location = new Uri(UriHelper.GetRequestUri(Request),
                                                        String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                }
                response.StatusCode = HttpStatusCode.Accepted;
                break;

            case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                // Should never hit this for zip push deploy
                response.StatusCode = HttpStatusCode.Forbidden;
                _tracer.Trace("Scm is not enabled, reject all requests.");
                break;

            case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_AutoSwapDeploymentOngoing);
                break;

            case FetchDeploymentRequestResult.Pending:
                // Shouldn't happen here, as we disallow deferral for this use case
                response.StatusCode = HttpStatusCode.Accepted;
                break;

            case FetchDeploymentRequestResult.RanSynchronously:
                response.StatusCode = HttpStatusCode.OK;
                break;

            case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_DeploymentInProgress);
                break;

            case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_RunFromRemoteZipConfigured);
                break;

            default:
                response.StatusCode = HttpStatusCode.BadRequest;
                break;
            }

            return(response);
        }
        public async Task Invoke(
            HttpContext context,
            ITracer tracer,
            IDeploymentSettingsManager settings,
            IFetchDeploymentManager manager,
            IEnumerable <IServiceHookHandler> serviceHookHandlers)
        {
            using (tracer.Step("FetchHandler"))
            {
                // Redirect GET /deploy requests to the Kudu root for convenience when using URL from Azure portal
                if (string.Equals(context.Request.Method, "GET", StringComparison.OrdinalIgnoreCase))
                {
                    context.Response.Redirect("/");
                    return;
                }

                if (!string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase))
                {
                    context.Response.StatusCode = StatusCodes.Status404NotFound;
                    return;
                }

                // CORE TODO Need to set up UseDeveloperExceptionPage, UseExceptionHandler or the like in startup
                //context.Response.TrySkipIisCustomErrors = true;

                DeploymentInfoBase deployInfo = null;

                // We are going to assume that the branch details are already set by the time it gets here. This is particularly important in the mercurial case,
                // since Settings hardcodes the default value for Branch to be "master". Consequently, Kudu will NoOp requests for Mercurial commits.
                var targetBranch = settings.GetBranch();
                try
                {
                    JObject      payload = GetPayload(context.Request, tracer);
                    DeployAction action  = GetRepositoryInfo(context.Request, payload, targetBranch, serviceHookHandlers, tracer, out deployInfo);
                    if (action == DeployAction.NoOp)
                    {
                        tracer.Trace("No-op for deployment.");
                        return;
                    }
                }
                catch (FormatException ex)
                {
                    tracer.TraceError(ex);
                    context.Response.StatusCode = StatusCodes.Status400BadRequest;
                    await context.Response.WriteAsync(ex.Message);

                    return;
                }

                // CORE TODO make sure .Query has the same semantics as the old .QueryString (null, empty, etc.)
                bool asyncRequested = String.Equals(context.Request.Query["isAsync"], "true", StringComparison.OrdinalIgnoreCase);

                var response = await manager.FetchDeploy(deployInfo, asyncRequested, UriHelper.GetRequestUri(context.Request), targetBranch);

                switch (response)
                {
                case FetchDeploymentRequestResult.RunningAynschronously:
                    // to avoid regression, only set location header if isAsync
                    if (asyncRequested)
                    {
                        // latest deployment keyword reserved to poll till deployment done
                        context.Response.Headers["Location"] = new Uri(UriHelper.GetRequestUri(context.Request),
                                                                       String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deployInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ"))).ToString();
                    }
                    context.Response.StatusCode = StatusCodes.Status202Accepted;
                    return;

                case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                    context.Response.StatusCode = StatusCodes.Status403Forbidden;
                    tracer.Trace("Scm is not enabled, reject all requests.");
                    return;

                case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                    context.Response.StatusCode = StatusCodes.Status409Conflict;
                    await context.Response.WriteAsync(Resources.Error_AutoSwapDeploymentOngoing);

                    return;

                case FetchDeploymentRequestResult.Pending:
                    // Return a http 202: the request has been accepted for processing, but the processing has not been completed.
                    context.Response.StatusCode = StatusCodes.Status202Accepted;
                    return;

                case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                    context.Response.StatusCode = StatusCodes.Status409Conflict;
                    await context.Response.WriteAsync(Resources.Error_DeploymentInProgress);

                    return;

                case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured:
                    context.Response.StatusCode = StatusCodes.Status409Conflict;
                    await context.Response.WriteAsync(Resources.Error_RunFromRemoteZipConfigured);

                    return;

                case FetchDeploymentRequestResult.RanSynchronously:
                default:
                    context.Response.StatusCode = StatusCodes.Status200OK;
                    break;
                }
            }
        }
        private async Task <IActionResult> PushDeployAsync(ZipDeploymentInfo deploymentInfo, bool isAsync,
                                                           HttpContext context)
        {
            var zipFilePath = Path.Combine(_environment.ZipTempPath, Guid.NewGuid() + ".zip");

            if (_settings.RunFromLocalZip())
            {
                await WriteSitePackageZip(deploymentInfo, _tracer);
            }
            else
            {
                var oryxManifestFile = Path.Combine(_environment.WebRootPath, "oryx-manifest.toml");
                if (FileSystemHelpers.FileExists(oryxManifestFile))
                {
                    _tracer.Step("Removing previous build artifact's manifest file");
                    FileSystemHelpers.DeleteFileSafe(oryxManifestFile);
                }

                try
                {
                    var nodeModulesSymlinkFile       = Path.Combine(_environment.WebRootPath, "node_modules");
                    Mono.Unix.UnixSymbolicLinkInfo i = new Mono.Unix.UnixSymbolicLinkInfo(nodeModulesSymlinkFile);
                    if (i.FileType == Mono.Unix.FileTypes.SymbolicLink)
                    {
                        _tracer.Step("Removing node_modules symlink");
                        // TODO: Add support to remove Unix Symlink File in DeleteFileSafe
                        // FileSystemHelpers.DeleteFileSafe(nodeModulesSymlinkFile);
                        FileSystemHelpers.RemoveUnixSymlink(nodeModulesSymlinkFile, TimeSpan.FromSeconds(5));
                    }
                }
                catch (Exception)
                {
                    // best effort
                }

                using (_tracer.Step("Writing zip file to {0}", zipFilePath))
                {
                    if (!string.IsNullOrEmpty(context.Request.ContentType) &&
                        context.Request.ContentType.Contains("multipart/form-data", StringComparison.OrdinalIgnoreCase))
                    {
                        FormValueProvider formModel;
                        using (_tracer.Step("Writing zip file to {0}", zipFilePath))
                        {
                            using (var file = System.IO.File.Create(zipFilePath))
                            {
                                formModel = await Request.StreamFile(file);
                            }
                        }
                    }
                    else if (deploymentInfo.ZipURL != null)
                    {
                        using (_tracer.Step("Writing zip file from packageUri to {0}", zipFilePath))
                        {
                            using (var httpClient = new HttpClient())
                                using (var fileStream = new FileStream(zipFilePath,
                                                                       FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
                                {
                                    var zipUrlRequest  = new HttpRequestMessage(HttpMethod.Get, deploymentInfo.ZipURL);
                                    var zipUrlResponse = await httpClient.SendAsync(zipUrlRequest);

                                    try
                                    {
                                        zipUrlResponse.EnsureSuccessStatusCode();
                                    }
                                    catch (HttpRequestException hre)
                                    {
                                        _tracer.TraceError(hre, "Failed to get file from packageUri {0}", deploymentInfo.ZipURL);
                                        throw;
                                    }

                                    using (var content = await zipUrlResponse.Content.ReadAsStreamAsync())
                                    {
                                        await content.CopyToAsync(fileStream);
                                    }
                                }
                        }
                    }
                    else
                    {
                        using (var file = System.IO.File.Create(zipFilePath))
                        {
                            await Request.Body.CopyToAsync(file);
                        }
                    }
                }

                deploymentInfo.RepositoryUrl = zipFilePath;
            }

            var result =
                await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD");

            switch (result)
            {
            case FetchDeploymentRequestResult.RunningAynschronously:
                if (isAsync)
                {
                    // latest deployment keyword reserved to poll till deployment done
                    Response.GetTypedHeaders().Location =
                        new Uri(UriHelper.GetRequestUri(Request),
                                String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment,
                                              deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                }

                return(Accepted());

            case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                // Should never hit this for zip push deploy
                _tracer.Trace("Scm is not enabled, reject all requests.");
                return(Forbid());

            case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_AutoSwapDeploymentOngoing));

            case FetchDeploymentRequestResult.Pending:
                // Shouldn't happen here, as we disallow deferral for this use case
                return(Accepted());

            case FetchDeploymentRequestResult.RanSynchronously:
                return(Ok());

            case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_DeploymentInProgress));

            case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_RunFromRemoteZipConfigured));

            default:
                return(BadRequest());
            }
        }
Beispiel #5
0
        public override async Task ProcessRequestAsync(HttpContext context)
        {
            using (_tracer.Step("FetchHandler"))
            {
                // Redirect GET /deploy requests to the Kudu root for convenience when using URL from Azure portal
                if (String.Equals(context.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
                {
                    context.Response.Redirect("~/");
                    context.ApplicationInstance.CompleteRequest();
                    return;
                }

                if (!String.Equals(context.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase))
                {
                    context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    context.ApplicationInstance.CompleteRequest();
                    return;
                }

                context.Response.TrySkipIisCustomErrors = true;

                DeploymentInfoBase deployInfo = null;

                // We are going to assume that the branch details are already set by the time it gets here. This is particularly important in the mercurial case,
                // since Settings hardcodes the default value for Branch to be "master". Consequently, Kudu will NoOp requests for Mercurial commits.
                string targetBranch = _settings.GetBranch();
                try
                {
                    var          request = new HttpRequestWrapper(context.Request);
                    JObject      payload = GetPayload(request);
                    DeployAction action  = GetRepositoryInfo(request, payload, targetBranch, out deployInfo);
                    if (action == DeployAction.NoOp)
                    {
                        _tracer.Trace("No-op for deployment.");
                        return;
                    }
                }
                catch (FormatException ex)
                {
                    _tracer.TraceError(ex);
                    context.Response.StatusCode = 400;
                    context.Response.Write(ex.Message);
                    context.ApplicationInstance.CompleteRequest();
                    return;
                }

                bool asyncRequested = String.Equals(context.Request.QueryString["isAsync"], "true", StringComparison.OrdinalIgnoreCase);

                var response = await _manager.FetchDeploy(deployInfo, asyncRequested, UriHelper.GetRequestUri(context.Request), targetBranch);

                switch (response)
                {
                case FetchDeploymentRequestResult.RunningAynschronously:
                    // to avoid regression, only set location header if isAsync
                    if (asyncRequested)
                    {
                        // latest deployment keyword reserved to poll till deployment done
                        context.Response.Headers["Location"] = new Uri(UriHelper.GetRequestUri(context.Request),
                                                                       String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deployInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ"))).ToString();
                    }
                    context.Response.StatusCode = (int)HttpStatusCode.Accepted;
                    context.ApplicationInstance.CompleteRequest();
                    return;

                case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                    context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                    context.ApplicationInstance.CompleteRequest();
                    _tracer.Trace("Scm is not enabled, reject all requests.");
                    return;

                case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                    context.Response.StatusCode = (int)HttpStatusCode.Conflict;
                    context.Response.Write(Resources.Error_AutoSwapDeploymentOngoing);
                    context.ApplicationInstance.CompleteRequest();
                    return;

                case FetchDeploymentRequestResult.Pending:
                    // Return a http 202: the request has been accepted for processing, but the processing has not been completed.
                    context.Response.StatusCode = (int)HttpStatusCode.Accepted;
                    context.ApplicationInstance.CompleteRequest();
                    return;

                case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                    context.Response.StatusCode = (int)HttpStatusCode.Conflict;
                    context.Response.Write(Resources.Error_DeploymentInProgress);
                    context.ApplicationInstance.CompleteRequest();
                    break;

                case FetchDeploymentRequestResult.RanSynchronously:
                default:
                    break;
                }
            }
        }
Beispiel #6
0
        private async Task <IActionResult> PushDeployAsync(ZipDeploymentInfo deploymentInfo, bool isAsync)
        {
            var zipFilePath = Path.Combine(_environment.ZipTempPath, Guid.NewGuid() + ".zip");

            if (_settings.RunFromLocalZip())
            {
                await WriteSitePackageZip(deploymentInfo, _tracer);
            }
            else
            {
                using (_tracer.Step("Writing zip file to {0}", zipFilePath))
                {
                    if (HttpContext.Request.ContentType.Contains("multipart/form-data",
                                                                 StringComparison.OrdinalIgnoreCase))
                    {
                        FormValueProvider formModel;
                        using (_tracer.Step("Writing zip file to {0}", zipFilePath))
                        {
                            using (var file = System.IO.File.Create(zipFilePath))
                            {
                                formModel = await Request.StreamFile(file);
                            }
                        }
                    }
                    else
                    {
                        using (var file = System.IO.File.Create(zipFilePath))
                        {
                            await Request.Body.CopyToAsync(file);
                        }
                    }
                }
                deploymentInfo.RepositoryUrl = zipFilePath;
            }

            var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD");

            switch (result)
            {
            case FetchDeploymentRequestResult.RunningAynschronously:
                if (isAsync)
                {
                    // latest deployment keyword reserved to poll till deployment done
                    Response.GetTypedHeaders().Location =
                        new Uri(UriHelper.GetRequestUri(Request),
                                String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                }
                return(Accepted());

            case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                // Should never hit this for zip push deploy
                _tracer.Trace("Scm is not enabled, reject all requests.");
                return(Forbid());

            case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_AutoSwapDeploymentOngoing));

            case FetchDeploymentRequestResult.Pending:
                // Shouldn't happen here, as we disallow deferral for this use case
                return(Accepted());

            case FetchDeploymentRequestResult.RanSynchronously:
                return(Ok());

            case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_DeploymentInProgress));

            case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured:
                return(StatusCode(StatusCodes.Status409Conflict, Resources.Error_AutoSwapDeploymentOngoing));

            default:
                return(BadRequest());
            }
        }
Beispiel #7
0
        public async Task <HttpResponseMessage> ZipPushDeploy(
            HttpRequestMessage request,
            [FromUri] bool isAsync       = false,
            [FromUri] string author      = null,
            [FromUri] string authorEmail = null,
            [FromUri] string deployer    = DefaultDeployer,
            [FromUri] string message     = DefaultMessage)
        {
            using (_tracer.Step("ZipPushDeploy"))
            {
                var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip");
                var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName);

                using (_tracer.Step("Writing zip file to {0}", zipFilePath))
                {
                    using (var file = FileSystemHelpers.CreateFile(zipFilePath))
                    {
                        await request.Content.CopyToAsync(file);
                    }
                }

                var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory)
                {
                    AllowDeploymentWhileScmDisabled = true,
                    Deployer                = deployer,
                    IsContinuous            = false,
                    AllowDeferredDeployment = false,
                    IsReusable              = false,
                    RepositoryUrl           = zipFilePath,
                    TargetChangeset         = DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed zip file"),
                    CommitId                = null,
                    RepositoryType          = RepositoryType.None,
                    Fetch = LocalZipFetch,
                    DoFullBuildByDefault = false,
                    Author      = author,
                    AuthorEmail = authorEmail,
                    Message     = message
                };

                var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, UriHelper.GetRequestUri(Request), "HEAD");

                var response = request.CreateResponse();

                switch (result)
                {
                case FetchDeploymentRequestResult.RunningAynschronously:
                    if (isAsync)
                    {
                        // latest deployment keyword reserved to poll till deployment done
                        response.Headers.Location = new Uri(UriHelper.GetRequestUri(Request),
                                                            String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                    }
                    response.StatusCode = HttpStatusCode.Accepted;
                    break;

                case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                    // Should never hit this for zip push deploy
                    response.StatusCode = HttpStatusCode.Forbidden;
                    _tracer.Trace("Scm is not enabled, reject all requests.");
                    break;

                case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                    response.StatusCode = HttpStatusCode.Conflict;
                    response.Content    = new StringContent(Resources.Error_AutoSwapDeploymentOngoing);
                    break;

                case FetchDeploymentRequestResult.Pending:
                    // Shouldn't happen here, as we disallow deferral for this use case
                    response.StatusCode = HttpStatusCode.Accepted;
                    break;

                case FetchDeploymentRequestResult.RanSynchronously:
                    response.StatusCode = HttpStatusCode.OK;
                    break;

                case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                    response.StatusCode = HttpStatusCode.Conflict;
                    response.Content    = new StringContent(Resources.Error_DeploymentInProgress);
                    break;

                default:
                    response.StatusCode = HttpStatusCode.BadRequest;
                    break;
                }

                return(response);
            }
        }
        private async Task <HttpResponseMessage> PushDeployAsync(ArtifactDeploymentInfo deploymentInfo, bool isAsync, JObject requestObject = null, ArtifactType artifactType = ArtifactType.Zip)
        {
            var content       = Request.Content;
            var isRequestJSON = content.Headers?.ContentType?.MediaType?.Equals("application/json", StringComparison.OrdinalIgnoreCase);

            if (isRequestJSON == true)
            {
                try
                {
                    // Read the request body if it hasn't been read already
                    if (requestObject == null)
                    {
                        requestObject = await Request.Content.ReadAsAsync <JObject>();
                    }
                    deploymentInfo.RemoteURL = ArmUtils.IsArmRequest(Request) ? GetArticfactURLFromARMJSON(requestObject) : GetArtifactURLFromJSON(requestObject);
                }
                catch (Exception ex)
                {
                    return(ArmUtils.CreateErrorResponse(Request, HttpStatusCode.BadRequest, ex));
                }
            }
            // For zip artifacts (zipdeploy, wardeploy, onedeploy with type=zip), copy the request body in a temp zip file.
            // It will be extracted to the appropriate directory by the Fetch handler
            else if (artifactType == ArtifactType.Zip)
            {
                await _deploymentLock.LockHttpOperationAsync(async() =>
                {
                    if (_settings.RunFromLocalZip())
                    {
                        await WriteSitePackageZip(deploymentInfo, _tracer, Request.Content);
                    }
                    else
                    {
                        var zipFileName = Path.ChangeExtension(Path.GetRandomFileName(), "zip");
                        var zipFilePath = Path.Combine(_environment.ZipTempPath, zipFileName);

                        using (_tracer.Step("Saving request content to {0}", zipFilePath))
                        {
                            await content.CopyToAsync(zipFilePath, _tracer);
                        }

                        deploymentInfo.RepositoryUrl = zipFilePath;
                    }
                }, "Preparing zip package");
            }
            // Copy the request body to a temp file.
            // It will be moved to the appropriate directory by the Fetch handler
            else if (deploymentInfo.Deployer == Constants.OneDeploy)
            {
                await _deploymentLock.LockHttpOperationAsync(async() =>
                {
                    var artifactTempPath = Path.Combine(_environment.ZipTempPath, deploymentInfo.TargetFileName);
                    using (_tracer.Step("Saving request content to {0}", artifactTempPath))
                    {
                        await content.CopyToAsync(artifactTempPath, _tracer);
                    }

                    deploymentInfo.RepositoryUrl = artifactTempPath;
                }, "Preparing zip package");
            }

            isAsync = ArmUtils.IsArmRequest(Request) ? true : isAsync;

            var result = await _deploymentManager.FetchDeploy(deploymentInfo, isAsync, Request.GetRequestUri(), "HEAD");

            var response = Request.CreateResponse();

            switch (result)
            {
            case FetchDeploymentRequestResult.RunningAynschronously:
                if (ArmUtils.IsArmRequest(Request))
                {
                    DeployResult deployResult = new DeployResult();
                    response = Request.CreateResponse(HttpStatusCode.Accepted, ArmUtils.AddEnvelopeOnArmRequest(deployResult, Request));
                    string statusURL = GetStatusUrl(Request.Headers.Referrer ?? Request.RequestUri);
                    // Should not happen: If we couldn't make the URL, there must have been an error in the request
                    if (string.IsNullOrEmpty(statusURL))
                    {
                        var badResponse = Request.CreateResponse();
                        badResponse.StatusCode = HttpStatusCode.BadRequest;
                        return(badResponse);
                    }
                    // latest deployment keyword reserved to poll till deployment done
                    response.Headers.Location = new Uri(statusURL +
                                                        String.Format("/deployments/{0}?api-version=2018-02-01&deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                    response.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(ScmHostingConfigurations.ArmRetryAfterSeconds));
                }
                else if (isAsync)
                {
                    // latest deployment keyword reserved to poll till deployment done
                    response.Headers.Location = new Uri(Request.GetRequestUri(),
                                                        String.Format("/api/deployments/{0}?deployer={1}&time={2}", Constants.LatestDeployment, deploymentInfo.Deployer, DateTime.UtcNow.ToString("yyy-MM-dd_HH-mm-ssZ")));
                    response.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(ScmHostingConfigurations.ArmRetryAfterSeconds));
                }
                response.StatusCode = HttpStatusCode.Accepted;
                break;

            case FetchDeploymentRequestResult.ForbiddenScmDisabled:
                // Should never hit this for zip push deploy
                response.StatusCode = HttpStatusCode.Forbidden;
                _tracer.Trace("Scm is not enabled, reject all requests.");
                break;

            case FetchDeploymentRequestResult.ConflictAutoSwapOngoing:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_AutoSwapDeploymentOngoing);
                break;

            case FetchDeploymentRequestResult.Pending:
                // Shouldn't happen here, as we disallow deferral for this use case
                response.StatusCode = HttpStatusCode.Accepted;
                break;

            case FetchDeploymentRequestResult.RanSynchronously:
                response.StatusCode = HttpStatusCode.OK;
                break;

            case FetchDeploymentRequestResult.ConflictDeploymentInProgress:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_DeploymentInProgress);
                break;

            case FetchDeploymentRequestResult.ConflictRunFromRemoteZipConfigured:
                response.StatusCode = HttpStatusCode.Conflict;
                response.Content    = new StringContent(Resources.Error_RunFromRemoteZipConfigured);
                break;

            default:
                response.StatusCode = HttpStatusCode.BadRequest;
                break;
            }

            return(response);
        }