File: Tasks\OneDeploy\DeploymentResponse.cs
Web Access
Project: ..\..\..\src\WebSdk\Publish\Tasks\Microsoft.NET.Sdk.Publish.Tasks.csproj (Microsoft.NET.Sdk.Publish.Tasks)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Text.Json.Serialization;
using Microsoft.NET.Sdk.Publish.Tasks.Properties;
 
namespace Microsoft.NET.Sdk.Publish.Tasks.OneDeploy;
 
/// <summary>
/// Represents the JSON response of a deployment operation.
/// </summary>
internal class DeploymentResponse
{
    internal static readonly DeploymentResponse s_unknownResponse = new()
    {
        Status = DeploymentStatus.Unknown,
    };
 
    [JsonPropertyName("id")]
    public string? Id { get; set; }
 
    [JsonPropertyName("end_time")]
    public string? EndTime { get; set; }
 
    [JsonPropertyName("log_url")]
    public string? LogUrl { get; set; }
 
    [JsonPropertyName("message")]
    public string? Message { get; set; }
 
    [JsonPropertyName("status")]
    public DeploymentStatus? Status { get; set; } = DeploymentStatus.Unknown;
 
    [JsonPropertyName("site_name")]
    public string? SiteName { get; set; }
 
    [JsonPropertyName("status_text")]
    public string? StatusText { get; set; }
 
    [JsonPropertyName("start_time")]
    public string? StartTime { get; set; }
 
    [JsonPropertyName("url")]
    public string? Url { get; set; }
 
    /// <inheritdoc/>
    public override string ToString()
    {
        return string.IsNullOrEmpty(StatusText)
            ? string.Format(Resources.DeploymentStatus, Status)
            : string.Format(Resources.DeploymentStatusWithText, Status, StatusText);
    }
}
 
/// <summary>
/// Extension methods for <see cref="DeploymentResponse"/>.
/// </summary>
internal static class DeploymentResponseExtensions
{
    internal static bool IsSuccessfulResponse(this DeploymentResponse response)
    {
        return response is not null
            && response.Status is not null
            && response.Status.Value.IsSuccessfulStatus();
    }
 
    internal static bool IsFailedResponse(this DeploymentResponse response)
    {
        return response is null
            || response.Status is null
            || response.Status.Value.IsFailedStatus();
    }
 
    public static string? GetLogUrlWithId(this DeploymentResponse deploymentResponse)
    {
        if (deploymentResponse is null
            || string.IsNullOrEmpty(deploymentResponse.LogUrl)
            || string.IsNullOrEmpty(deploymentResponse.Id))
        {
            return deploymentResponse?.LogUrl;
        }
 
        try
        {
            Uri logUrl = new(deploymentResponse.LogUrl);
            string pathAndQuery = logUrl.PathAndQuery;
 
            // try to replace '../latest/log' with '../{deploymentResponse.Id}/log'
            if (!string.IsNullOrEmpty(pathAndQuery))
            {
                string[] pathAndQueryParts = pathAndQuery.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
                string?[] pathWithIdParts = new string[pathAndQueryParts.Length];
 
                for (int i = pathAndQueryParts.Length - 1; i >= 0; i--)
                {
                    if (string.Equals("latest", pathAndQueryParts[i], StringComparison.Ordinal))
                    {
                        pathWithIdParts[i] = deploymentResponse.Id;
                        continue;
                    }
 
                    pathWithIdParts[i] = pathAndQueryParts[i].Trim();
                }
 
                return new UriBuilder()
                {
                    Scheme = logUrl.Scheme,
                    Host = logUrl.Host,
                    Path = string.Join("/", pathWithIdParts)
                }.ToString();
            }
        }
        catch
        {
            // do nothing
        }
 
        return deploymentResponse.LogUrl;
    }
}