Add option to set the base href.
This commit is contained in:
parent
dbfc348945
commit
8418b26d70
12 changed files with 107 additions and 39 deletions
|
|
@ -1,44 +1,45 @@
|
|||
import { APP_BASE_HREF } from '@angular/common';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AuthService {
|
||||
constructor(private http: HttpClient) {}
|
||||
constructor(private http: HttpClient, @Inject(APP_BASE_HREF) private baseHref: string) {}
|
||||
|
||||
public isLoggedIn(): Observable<boolean> {
|
||||
return this.http.get<boolean>(`/Api/Authentication/IsLoggedIn`);
|
||||
return this.http.get<boolean>(`${this.baseHref}Api/Authentication/IsLoggedIn`);
|
||||
}
|
||||
|
||||
public create(userName: string, password: string): Observable<void> {
|
||||
return this.http.post<void>(`/Api/Authentication/Create`, {
|
||||
return this.http.post<void>(`${this.baseHref}Api/Authentication/Create`, {
|
||||
userName,
|
||||
password,
|
||||
});
|
||||
}
|
||||
|
||||
public setupProvider(provider: string, token: string): Observable<void> {
|
||||
return this.http.post<void>(`/Api/Authentication/SetupProvider`, {
|
||||
return this.http.post<void>(`${this.baseHref}Api/Authentication/SetupProvider`, {
|
||||
provider,
|
||||
token,
|
||||
});
|
||||
}
|
||||
|
||||
public login(userName: string, password: string): Observable<void> {
|
||||
return this.http.post<void>(`/Api/Authentication/Login`, {
|
||||
return this.http.post<void>(`${this.baseHref}Api/Authentication/Login`, {
|
||||
userName,
|
||||
password,
|
||||
});
|
||||
}
|
||||
|
||||
public logout() {
|
||||
return this.http.post<void>(`/Api/Authentication/Logout`, {});
|
||||
return this.http.post<void>(`${this.baseHref}Api/Authentication/Logout`, {});
|
||||
}
|
||||
|
||||
public update(userName: string, password: string): Observable<void> {
|
||||
return this.http.post<void>(`/Api/Authentication/Update`, {
|
||||
return this.http.post<void>(`${this.baseHref}Api/Authentication/Update`, {
|
||||
userName,
|
||||
password,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<div class="container">
|
||||
<div class="columns is-centered">
|
||||
<div class="column is-5-tablet is-5-desktop is-5-widescreen">
|
||||
<img src="../../assets/logo.png" />
|
||||
<img src="assets/logo.png" />
|
||||
<div class="box">
|
||||
<form (ngSubmit)="login()">
|
||||
<div class="field">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<nav class="navbar is-dark is-fixed-top" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" routerLink="/">
|
||||
<img src="../../assets/logo.png" />
|
||||
<img src="assets/logo.png" />
|
||||
</a>
|
||||
|
||||
<a
|
||||
|
|
|
|||
|
|
@ -1,41 +1,42 @@
|
|||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Profile } from './models/profile.model';
|
||||
import { Setting } from './models/setting.model';
|
||||
import { APP_BASE_HREF } from '@angular/common';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class SettingsService {
|
||||
constructor(private http: HttpClient) {}
|
||||
constructor(private http: HttpClient, @Inject(APP_BASE_HREF) private baseHref: string) {}
|
||||
|
||||
public get(): Observable<Setting[]> {
|
||||
return this.http.get<Setting[]>(`/Api/Settings`);
|
||||
return this.http.get<Setting[]>(`${this.baseHref}Api/Settings`);
|
||||
}
|
||||
|
||||
public update(settings: Setting[]): Observable<void> {
|
||||
return this.http.put<void>(`/Api/Settings`, settings);
|
||||
return this.http.put<void>(`${this.baseHref}Api/Settings`, settings);
|
||||
}
|
||||
|
||||
public getProfile(): Observable<Profile> {
|
||||
return this.http.get<Profile>(`/Api/Settings/Profile`);
|
||||
return this.http.get<Profile>(`${this.baseHref}Api/Settings/Profile`);
|
||||
}
|
||||
|
||||
public testPath(path: string): Observable<void> {
|
||||
return this.http.post<void>(`/Api/Settings/TestPath`, { path });
|
||||
return this.http.post<void>(`${this.baseHref}Api/Settings/TestPath`, { path });
|
||||
}
|
||||
|
||||
public testDownloadSpeed(): Observable<number> {
|
||||
return this.http.get<number>(`/Api/Settings/TestDownloadSpeed`);
|
||||
return this.http.get<number>(`${this.baseHref}Api/Settings/TestDownloadSpeed`);
|
||||
}
|
||||
|
||||
public testWriteSpeed(): Observable<number> {
|
||||
return this.http.get<number>(`/Api/Settings/TestWriteSpeed`);
|
||||
return this.http.get<number>(`${this.baseHref}Api/Settings/TestWriteSpeed`);
|
||||
}
|
||||
|
||||
public testAria2cConnection(url: string, secret: string): Observable<{ version: string }> {
|
||||
return this.http.post<{ version: string }>(`/Api/Settings/TestAria2cConnection`, {
|
||||
return this.http.post<{ version: string }>(`${this.baseHref}Api/Settings/TestAria2cConnection`, {
|
||||
url,
|
||||
secret,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<div class="container">
|
||||
<div class="columns is-centered">
|
||||
<div class="column is-5-tablet is-5-desktop is-5-widescreen">
|
||||
<img src="../../assets/logo.png" />
|
||||
<img src="assets/logo.png" />
|
||||
<div class="box" *ngIf="step === 1">
|
||||
<div class="notification is-primary">
|
||||
Welcome to Real-Debrid Client. Please create your account by entering a username and password.
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
>Use this link to sign up to AllDebrid.</a
|
||||
>
|
||||
<br />
|
||||
<a href="https://www.premiumize.me/" target="_blank" rel="noopener"
|
||||
<a href="https://www.premiumize.me/" target="_blank" rel="noopener"
|
||||
>Use this link to sign up to Premiumize.</a
|
||||
>
|
||||
<br />
|
||||
|
|
@ -64,7 +64,7 @@
|
|||
<select [(ngModel)]="provider">
|
||||
<option [value]="0">Real-Debrid</option>
|
||||
<option [value]="1">AllDebrid</option>
|
||||
<option [value]="2">Premiumize</option>
|
||||
<option [value]="2">Premiumize</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -85,7 +85,7 @@
|
|||
>https://alldebrid.com/apikeys/</a
|
||||
>.
|
||||
</p>
|
||||
<p class="help" *ngIf="provider === 'Premiumize'">
|
||||
<p class="help" *ngIf="provider === 'Premiumize'">
|
||||
You can find your API key here:
|
||||
<a href="https://www.premiumize.me/account" target="_blank" rel="noopener"
|
||||
>https://www.premiumize.me/account</a
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import * as signalR from '@microsoft/signalr';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { Torrent, TorrentFileAvailability } from './models/torrent.model';
|
||||
import { APP_BASE_HREF } from '@angular/common';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -12,7 +13,7 @@ export class TorrentService {
|
|||
|
||||
private connection: signalR.HubConnection;
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
constructor(private http: HttpClient, @Inject(APP_BASE_HREF) private baseHref: string) {
|
||||
this.connect();
|
||||
}
|
||||
|
||||
|
|
@ -21,7 +22,10 @@ export class TorrentService {
|
|||
return;
|
||||
}
|
||||
|
||||
this.connection = new signalR.HubConnectionBuilder().withUrl('/hub').withAutomaticReconnect().build();
|
||||
this.connection = new signalR.HubConnectionBuilder()
|
||||
.withUrl(`${this.baseHref}hub`)
|
||||
.withAutomaticReconnect()
|
||||
.build();
|
||||
this.connection.start().catch((err) => console.error(err));
|
||||
|
||||
this.connection.on('update', (torrents: Torrent[]) => {
|
||||
|
|
@ -30,15 +34,15 @@ export class TorrentService {
|
|||
}
|
||||
|
||||
public getList(): Observable<Torrent[]> {
|
||||
return this.http.get<Torrent[]>(`/Api/Torrents`);
|
||||
return this.http.get<Torrent[]>(`${this.baseHref}Api/Torrents`);
|
||||
}
|
||||
|
||||
public get(torrentId: string): Observable<Torrent> {
|
||||
return this.http.get<Torrent>(`/Api/Torrents/Get/${torrentId}`);
|
||||
return this.http.get<Torrent>(`${this.baseHref}Api/Torrents/Get/${torrentId}`);
|
||||
}
|
||||
|
||||
public uploadMagnet(magnetLink: string, torrent: Torrent): Observable<void> {
|
||||
return this.http.post<void>(`/Api/Torrents/UploadMagnet`, {
|
||||
return this.http.post<void>(`${this.baseHref}Api/Torrents/UploadMagnet`, {
|
||||
magnetLink,
|
||||
torrent,
|
||||
});
|
||||
|
|
@ -48,11 +52,11 @@ export class TorrentService {
|
|||
const formData: FormData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('formData', JSON.stringify({ torrent }));
|
||||
return this.http.post<void>(`/Api/Torrents/UploadFile`, formData);
|
||||
return this.http.post<void>(`${this.baseHref}Api/Torrents/UploadFile`, formData);
|
||||
}
|
||||
|
||||
public checkFilesMagnet(magnetLink: string): Observable<TorrentFileAvailability[]> {
|
||||
return this.http.post<TorrentFileAvailability[]>(`/Api/Torrents/CheckFilesMagnet`, {
|
||||
return this.http.post<TorrentFileAvailability[]>(`${this.baseHref}Api/Torrents/CheckFilesMagnet`, {
|
||||
magnetLink,
|
||||
});
|
||||
}
|
||||
|
|
@ -60,7 +64,7 @@ export class TorrentService {
|
|||
public checkFiles(file: File): Observable<TorrentFileAvailability[]> {
|
||||
const formData: FormData = new FormData();
|
||||
formData.append('file', file);
|
||||
return this.http.post<TorrentFileAvailability[]>(`/Api/Torrents/CheckFiles`, formData);
|
||||
return this.http.post<TorrentFileAvailability[]>(`${this.baseHref}Api/Torrents/CheckFiles`, formData);
|
||||
}
|
||||
|
||||
public delete(
|
||||
|
|
@ -69,7 +73,7 @@ export class TorrentService {
|
|||
deleteRdTorrent: boolean,
|
||||
deleteLocalFiles: boolean
|
||||
): Observable<void> {
|
||||
return this.http.post<void>(`/Api/Torrents/Delete/${torrentId}`, {
|
||||
return this.http.post<void>(`${this.baseHref}Api/Torrents/Delete/${torrentId}`, {
|
||||
deleteData,
|
||||
deleteRdTorrent,
|
||||
deleteLocalFiles,
|
||||
|
|
@ -77,14 +81,14 @@ export class TorrentService {
|
|||
}
|
||||
|
||||
public retry(torrentId: string): Observable<void> {
|
||||
return this.http.post<void>(`/Api/Torrents/Retry/${torrentId}`, {});
|
||||
return this.http.post<void>(`${this.baseHref}Api/Torrents/Retry/${torrentId}`, {});
|
||||
}
|
||||
|
||||
public retryDownload(downloadId: string): Observable<void> {
|
||||
return this.http.post<void>(`/Api/Torrents/RetryDownload/${downloadId}`, {});
|
||||
return this.http.post<void>(`${this.baseHref}Api/Torrents/RetryDownload/${downloadId}`, {});
|
||||
}
|
||||
|
||||
public update(torrent: Torrent): Observable<void> {
|
||||
return this.http.put<void>(`/Api/Torrents/Update`, torrent);
|
||||
return this.http.put<void>(`${this.baseHref}Api/Torrents/Update`, torrent);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
<base href="/" />
|
||||
<script>
|
||||
(function () {
|
||||
window["_app_base"] = "/" + window.location.pathname.split("/")[1];
|
||||
var pathSegment = window.location.pathname.split("/")[1];
|
||||
window["_app_base"] = pathSegment ? "/" + pathSegment + "/" : "/";
|
||||
console.log("setting base href to " + window["_app_base"]);
|
||||
})();
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ public class AppSettings
|
|||
public AppSettingsDatabase? Database { get; set; }
|
||||
|
||||
public Int32 Port { get; set; }
|
||||
public String? BasePath { get; set; }
|
||||
}
|
||||
|
||||
public class AppSettingsLogging
|
||||
|
|
|
|||
54
server/RdtClient.Service/Middleware/BaseHrefMiddleware.cs
Normal file
54
server/RdtClient.Service/Middleware/BaseHrefMiddleware.cs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using RdtClient.Data.Models.Internal;
|
||||
|
||||
namespace RdtClient.Service.Middleware;
|
||||
|
||||
public class BaseHrefMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
public BaseHrefMiddleware(RequestDelegate next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context, AppSettings appSettings)
|
||||
{
|
||||
var originalBody = context.Response.Body;
|
||||
|
||||
try
|
||||
{
|
||||
using var newBody = new MemoryStream();
|
||||
|
||||
context.Response.Body = newBody;
|
||||
|
||||
await _next(context);
|
||||
|
||||
context.Response.Body = originalBody;
|
||||
newBody.Seek(0, SeekOrigin.Begin);
|
||||
var responseBody = await new StreamReader(newBody).ReadToEndAsync();
|
||||
|
||||
// ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract
|
||||
if (context.Response.ContentType?.Contains("text/html") == true)
|
||||
{
|
||||
var basePath = $"/{appSettings.BasePath!.TrimStart('/').TrimEnd('/')}/";
|
||||
|
||||
responseBody = Regex.Replace(responseBody, @"<base href=""/""", @$"<base href=""{basePath}""");
|
||||
|
||||
responseBody = Regex.Replace(responseBody, "(<script.*?src=\")(.*?)(\".*?</script>)", $"$1{basePath}$2$3");
|
||||
responseBody = Regex.Replace(responseBody, "(<link.*?href=\")(.*?)(\".*?>)", $"$1{basePath}$2$3");
|
||||
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
}
|
||||
else
|
||||
{
|
||||
await context.Response.BodyWriter.WriteAsync(newBody.ToArray());
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
context.Response.Body = originalBody;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -164,6 +164,11 @@ try
|
|||
}
|
||||
});
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(appSettings.BasePath))
|
||||
{
|
||||
app.UseMiddleware<BaseHrefMiddleware>();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthentication();
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
},
|
||||
"RdtClient.Web": {
|
||||
"commandName": "Project",
|
||||
"launchUrl": "weatherforecast",
|
||||
"launchUrl": "",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,5 +9,6 @@
|
|||
"Database": {
|
||||
"Path": "/data/db/rdtclient.db"
|
||||
},
|
||||
"Port": "6500"
|
||||
"Port": "6500",
|
||||
"BasePath": null
|
||||
}
|
||||
Loading…
Reference in a new issue