diff --git a/webui/src/app.sass b/webui/src/app.sass
index 64a380502..7d97267d6 100644
--- a/webui/src/app.sass
+++ b/webui/src/app.sass
@@ -25,3 +25,13 @@ html
font-family: $open-sans
height: 100%
background: $background
+
+.wip
+ display: flex
+ flex-direction: column
+ align-items: center
+ justify-content: center
+ height: 80vh
+
+ .title
+ font-size: 4em
diff --git a/webui/src/app/app.component.spec.ts b/webui/src/app/app.component.spec.ts
deleted file mode 100644
index ccface19f..000000000
--- a/webui/src/app/app.component.spec.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
-import { async, TestBed } from '@angular/core/testing';
-import { AppComponent } from './app.component';
-
-describe('AppComponent', () => {
- beforeEach(async(() => {
- TestBed.configureTestingModule({
- declarations: [AppComponent],
- schemas: [CUSTOM_ELEMENTS_SCHEMA]
- }).compileComponents();
- }));
-
- it('should create the app', async(() => {
- const fixture = TestBed.createComponent(AppComponent);
- const app = fixture.debugElement.componentInstance;
- expect(app).toBeTruthy();
- }));
-});
diff --git a/webui/src/app/app.component.ts b/webui/src/app/app.component.ts
index 5d475fee0..4218b7340 100644
--- a/webui/src/app/app.component.ts
+++ b/webui/src/app/app.component.ts
@@ -3,8 +3,12 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
-
-
+
+
+
+
`
})
export class AppComponent {}
diff --git a/webui/src/app/app.module.ts b/webui/src/app/app.module.ts
index bf18dad04..4bc979bfd 100644
--- a/webui/src/app/app.module.ts
+++ b/webui/src/app/app.module.ts
@@ -3,46 +3,11 @@ import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
-import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
-import { BarChartComponent } from './charts/bar-chart/bar-chart.component';
-import { LineChartComponent } from './charts/line-chart/line-chart.component';
-import { HeaderComponent } from './components/header/header.component';
-import { HealthComponent } from './components/health/health.component';
-import { ProvidersComponent } from './components/providers/providers.component';
-import { LetDirective } from './directives/let.directive';
-import { BackendFilterPipe } from './pipes/backend.filter.pipe';
-import { FrontendFilterPipe } from './pipes/frontend.filter.pipe';
-import { HumanReadableFilterPipe } from './pipes/humanreadable.filter.pipe';
-import { KeysPipe } from './pipes/keys.pipe';
-import { ApiService } from './services/api.service';
-import { WindowService } from './services/window.service';
@NgModule({
- declarations: [
- AppComponent,
- HeaderComponent,
- ProvidersComponent,
- HealthComponent,
- LineChartComponent,
- BarChartComponent,
- KeysPipe,
- FrontendFilterPipe,
- BackendFilterPipe,
- HumanReadableFilterPipe,
- LetDirective
- ],
- imports: [
- BrowserModule,
- CommonModule,
- HttpClientModule,
- FormsModule,
- RouterModule.forRoot([
- { path: '', component: ProvidersComponent, pathMatch: 'full' },
- { path: 'status', component: HealthComponent }
- ])
- ],
- providers: [ApiService, WindowService],
+ declarations: [AppComponent],
+ imports: [BrowserModule, CommonModule, HttpClientModule, FormsModule],
bootstrap: [AppComponent]
})
export class AppModule {}
diff --git a/webui/src/app/charts/bar-chart/bar-chart.component.html b/webui/src/app/charts/bar-chart/bar-chart.component.html
deleted file mode 100644
index 129efa0c2..000000000
--- a/webui/src/app/charts/bar-chart/bar-chart.component.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
- Loading, please wait...
-
-
-
diff --git a/webui/src/app/charts/bar-chart/bar-chart.component.spec.ts b/webui/src/app/charts/bar-chart/bar-chart.component.spec.ts
deleted file mode 100644
index 1b743e942..000000000
--- a/webui/src/app/charts/bar-chart/bar-chart.component.spec.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { WindowService } from '../../services/window.service';
-import { BarChartComponent } from './bar-chart.component';
-
-describe('BarChartComponent', () => {
- let component: BarChartComponent;
- let fixture: ComponentFixture;
-
- beforeEach(async(() => {
- TestBed.configureTestingModule({
- declarations: [BarChartComponent],
- providers: [{ provide: WindowService, useInstance: {} }]
- }).compileComponents();
- }));
-
- beforeEach(() => {
- fixture = TestBed.createComponent(BarChartComponent);
- component = fixture.componentInstance;
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-
- it('should initially go to loading state', () => {
- expect(component.loading).toBeTruthy();
- });
-});
diff --git a/webui/src/app/charts/bar-chart/bar-chart.component.ts b/webui/src/app/charts/bar-chart/bar-chart.component.ts
deleted file mode 100644
index 47b6d2307..000000000
--- a/webui/src/app/charts/bar-chart/bar-chart.component.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-import {
- Component,
- ElementRef,
- Input,
- OnChanges,
- OnInit,
- SimpleChanges
-} from '@angular/core';
-import { axisBottom, axisLeft, max, scaleBand, scaleLinear, select } from 'd3';
-import { format } from 'd3-format';
-import * as _ from 'lodash';
-import { WindowService } from '../../services/window.service';
-
-@Component({
- selector: 'app-bar-chart',
- templateUrl: './bar-chart.component.html'
-})
-export class BarChartComponent implements OnInit, OnChanges {
- @Input() value: any;
-
- barChartEl: HTMLElement;
- svg: any;
- x: any;
- y: any;
- g: any;
- width: number;
- height: number;
- margin = { top: 40, right: 40, bottom: 40, left: 40 };
- loading: boolean;
- data: any[];
- previousData: any[];
-
- constructor(
- public elementRef: ElementRef,
- public windowService: WindowService
- ) {
- this.loading = true;
- }
-
- ngOnInit() {
- this.barChartEl = this.elementRef.nativeElement.querySelector('.bar-chart');
- this.setup();
- setTimeout(() => (this.loading = false), 1000);
-
- this.windowService.resize.subscribe(w => this.draw());
- }
-
- ngOnChanges(changes: SimpleChanges) {
- if (!this.value || !this.svg) {
- return;
- }
-
- if (!_.isEqual(this.previousData, this.value)) {
- this.previousData = _.cloneDeep(this.value);
- this.data = this.value;
-
- this.draw();
- }
- }
-
- setup(): void {
- this.width =
- this.barChartEl.clientWidth - this.margin.left - this.margin.right;
- this.height =
- this.barChartEl.clientHeight - this.margin.top - this.margin.bottom;
-
- this.svg = select(this.barChartEl)
- .append('svg')
- .attr('width', this.width + this.margin.left + this.margin.right)
- .attr('height', this.height + this.margin.top + this.margin.bottom);
-
- this.g = this.svg
- .append('g')
- .attr('transform', `translate(${this.margin.left}, ${this.margin.top})`);
-
- this.x = scaleBand().padding(0.05);
- this.y = scaleLinear();
-
- this.g.append('g').attr('class', 'axis axis--x');
-
- this.g.append('g').attr('class', 'axis axis--y');
- }
-
- draw(): void {
- if (
- this.barChartEl.clientWidth === 0 ||
- this.barChartEl.clientHeight === 0
- ) {
- this.previousData = [];
- } else {
- this.width =
- this.barChartEl.clientWidth - this.margin.left - this.margin.right;
- this.height =
- this.barChartEl.clientHeight - this.margin.top - this.margin.bottom;
- }
-
- this.x.domain(this.data.map((d: any) => d.code));
- this.y.domain([0, max(this.data, (d: any) => d.count)]);
-
- this.svg
- .attr('width', this.width + this.margin.left + this.margin.right)
- .attr('height', this.height + this.margin.top + this.margin.bottom);
-
- this.x.rangeRound([0, this.width]);
- this.y.rangeRound([this.height, 0]);
-
- this.g
- .select('.axis--x')
- .attr('transform', `translate(0, ${this.height})`)
- .call(axisBottom(this.x));
-
- this.g.select('.axis--y').call(
- axisLeft(this.y)
- .tickFormat(format('~s'))
- .tickSize(-this.width)
- );
-
- // Clean previous graph
- this.g.selectAll('.bar').remove();
-
- const bars = this.g.selectAll('.bar').data(this.data);
-
- bars
- .enter()
- .append('rect')
- .attr('class', 'bar')
- .style(
- 'fill',
- (d: any) =>
- 'hsl(' + Math.floor(((d.code - 100) * 310) / 427 + 50) + ', 50%, 50%)'
- )
- .attr('x', (d: any) => this.x(d.code))
- .attr('y', (d: any) => this.y(d.count))
- .attr('width', this.x.bandwidth())
- .attr('height', (d: any) =>
- this.height - this.y(d.count) < 0 ? 0 : this.height - this.y(d.count)
- );
-
- bars.exit().remove();
- }
-}
diff --git a/webui/src/app/charts/line-chart/line-chart.component.html b/webui/src/app/charts/line-chart/line-chart.component.html
deleted file mode 100644
index 99c13f597..000000000
--- a/webui/src/app/charts/line-chart/line-chart.component.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
- Loading, please wait...
-
-
-
diff --git a/webui/src/app/charts/line-chart/line-chart.component.ts b/webui/src/app/charts/line-chart/line-chart.component.ts
deleted file mode 100644
index 0ecbb7067..000000000
--- a/webui/src/app/charts/line-chart/line-chart.component.ts
+++ /dev/null
@@ -1,240 +0,0 @@
-import {
- Component,
- ElementRef,
- Input,
- OnChanges,
- OnInit,
- SimpleChanges
-} from '@angular/core';
-import {
- axisBottom,
- axisLeft,
- curveLinear,
- easeLinear,
- line,
- max,
- min,
- range,
- scaleLinear,
- scaleTime,
- select,
- timeFormat,
- timeSecond
-} from 'd3';
-import { WindowService } from '../../services/window.service';
-
-@Component({
- selector: 'app-line-chart',
- templateUrl: 'line-chart.component.html'
-})
-export class LineChartComponent implements OnChanges, OnInit {
- @Input() value: { count: number; date: string };
-
- firstDisplay: boolean;
- dirty: boolean;
- lineChartEl: HTMLElement;
- loadingEl: HTMLElement;
- svg: any;
- g: any;
- line: any;
- path: any;
- x: any;
- y: any;
- data: number[];
- now: Date;
- duration: number;
- limit: number;
- options: any;
- xAxis: any;
- yAxis: any;
- height: number;
- width: number;
- margin = { top: 40, right: 40, bottom: 60, left: 60 };
- loading = true;
-
- constructor(
- private elementRef: ElementRef,
- public windowService: WindowService
- ) {}
-
- ngOnInit() {
- this.lineChartEl = this.elementRef.nativeElement.querySelector(
- '.line-chart'
- );
- this.loadingEl = this.elementRef.nativeElement.querySelector(
- '.line-chart-loading'
- );
- this.limit = 40;
-
- // related to the Observable.timer(0, 3000) in health component
- this.duration = 3000;
-
- this.now = new Date(Date.now() - this.duration);
-
- this.options = {
- title: '',
- color: '#3A84C5'
- };
-
- this.firstDisplay = true;
- this.render();
-
- this.windowService.resize.subscribe(w => {
- if (this.svg) {
- this.dirty = true;
- this.loading = true;
- this.render();
- }
- });
- }
-
- render() {
- // When the lineChartEl is not displayed (is-hidden), width and length are equal to 0.
- let elt;
- if (
- this.lineChartEl.clientWidth === 0 ||
- this.lineChartEl.clientHeight === 0
- ) {
- elt = this.loadingEl;
- } else {
- elt = this.lineChartEl;
- }
- this.width = elt.clientWidth - this.margin.left - this.margin.right;
- this.height = elt.clientHeight - this.margin.top - this.margin.bottom;
-
- const el = this.lineChartEl.querySelector('svg');
- if (el) {
- el.parentNode.removeChild(el);
- }
-
- this.svg = select(this.lineChartEl)
- .append('svg')
- .attr('width', this.width + this.margin.left + this.margin.right)
- .attr('height', this.height + this.margin.top + this.margin.bottom)
- .append('g')
- .attr('transform', `translate(${this.margin.left}, ${this.margin.top})`);
-
- if (!this.data) {
- this.data = range(this.limit).map(i => 0);
- }
-
- this.x = scaleTime().range([0, this.width - 10]);
- this.y = scaleLinear().range([this.height, 0]);
-
- this.x.domain([
- (this.now as any) - (this.limit - 2),
- (this.now as any) - this.duration
- ]);
- this.y.domain([0, max(this.data, (d: any) => d)]);
-
- this.line = line()
- .x((d: any, i: number) =>
- this.x((this.now as any) - (this.limit - 1 - i) * this.duration)
- )
- .y((d: any) => this.y(d))
- .curve(curveLinear);
-
- this.svg
- .append('defs')
- .append('clipPath')
- .attr('id', 'clip')
- .append('rect')
- .attr('width', this.width)
- .attr('height', this.height);
-
- this.xAxis = this.svg
- .append('g')
- .attr('class', 'x axis')
- .attr('transform', `translate(0, ${this.height})`)
- .call(
- axisBottom(this.x)
- .tickSize(-this.height)
- .ticks(timeSecond, 5)
- .tickFormat(timeFormat('%H:%M:%S'))
- );
-
- this.yAxis = this.svg
- .append('g')
- .attr('class', 'y axis')
- .call(axisLeft(this.y).tickSize(-this.width));
-
- this.path = this.svg
- .append('g')
- .attr('clip-path', 'url(#clip)')
- .append('path')
- .data([this.data])
- .attr('class', 'line');
- }
-
- ngOnChanges(changes: SimpleChanges) {
- if (!this.value || !this.svg) {
- return;
- }
-
- this.updateData(this.value.count);
- }
-
- updateData(value: number) {
- this.data.push(value * 1000000);
- this.now = new Date();
-
- this.x.domain([
- (this.now as any) - (this.limit - 2) * this.duration,
- (this.now as any) - this.duration
- ]);
- const minv =
- min(this.data, (d: any) => d) > 0 ? min(this.data, (d: any) => d) - 4 : 0;
- const maxv = max(this.data, (d: any) => d) + 4;
- this.y.domain([minv, maxv]);
-
- this.xAxis
- .transition()
- .duration(this.firstDisplay || this.dirty ? 0 : this.duration)
- .ease(easeLinear)
- .call(
- axisBottom(this.x)
- .tickSize(-this.height)
- .ticks(timeSecond, 5)
- .tickFormat(timeFormat('%H:%M:%S'))
- );
-
- this.xAxis
- .transition()
- .duration(0)
- .selectAll('text')
- .style('text-anchor', 'end')
- .attr('dx', '-.8em')
- .attr('dy', '.15em')
- .attr('transform', 'rotate(-65)');
-
- this.yAxis
- .transition()
- .duration(500)
- .ease(easeLinear)
- .call(axisLeft(this.y).tickSize(-this.width));
-
- this.path
- .transition()
- .duration(0)
- .attr('d', this.line(this.data))
- .attr('transform', null)
- .transition()
- .duration(this.duration)
- .ease(easeLinear)
- .attr(
- 'transform',
- `translate(${this.x(
- (this.now as any) - (this.limit - 1) * this.duration
- )})`
- );
-
- this.firstDisplay = false;
- this.dirty = false;
-
- if (this.loading) {
- this.loading = false;
- }
-
- this.data.shift();
- }
-}
diff --git a/webui/src/app/components/header/header.component.html b/webui/src/app/components/header/header.component.html
deleted file mode 100644
index f41266a64..000000000
--- a/webui/src/app/components/header/header.component.html
+++ /dev/null
@@ -1,57 +0,0 @@
-
diff --git a/webui/src/app/components/header/header.component.ts b/webui/src/app/components/header/header.component.ts
deleted file mode 100644
index 52960be9b..000000000
--- a/webui/src/app/components/header/header.component.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { ApiService } from '../../services/api.service';
-
-@Component({
- selector: 'app-header',
- templateUrl: 'header.component.html'
-})
-export class HeaderComponent implements OnInit {
- version: string;
- codename: string;
- releaseLink: string;
- burger: boolean;
-
- constructor(private apiService: ApiService) {}
-
- ngOnInit() {
- this.apiService.fetchVersion().subscribe(data => {
- this.version = data.Version;
- this.codename = data.Codename;
- this.releaseLink =
- 'https://github.com/containous/traefik/tree/' + data.Version;
- });
- }
-}
diff --git a/webui/src/app/components/health/health.component.html b/webui/src/app/components/health/health.component.html
deleted file mode 100644
index 4125d3985..000000000
--- a/webui/src/app/components/health/health.component.html
+++ /dev/null
@@ -1,116 +0,0 @@
-
-
-
-
-
-
-
-
-
- Total Response Time
- {{
- totalResponseTime
- }}
-
-
-
-
- Total Code Count
- {{ totalCodeCount }}
-
-
-
-
- Uptime Since
{{ uptimeSince }}
- {{ uptime }}
-
-
-
-
-
-
-
-
-
-
- Average Response Time
- {{
- averageResponseTime
- }}
-
-
-
-
- Code Count
- {{ codeCount }}
-
-
-
-
-
-
-
-
-
-
-
-
-
Average Response Time (µs)
-
-
-
-
-
-
Total Status Code Count
-
-
-
-
-
-
-
-
-
-
-
Recent HTTP Errors
-
-
- Status |
- Request |
- Time |
-
-
-
- {{
- entry.status_code
- }} {{
- entry.status
- }}
- |
-
- {{ entry.method }} {{ entry.host }}{{ entry.path }}
- |
-
- {{
- entry.time | date: 'yyyy-MM-dd HH:mm:ss a z'
- }}
- |
-
-
-
- No entries
- |
-
-
-
-
-
diff --git a/webui/src/app/components/health/health.component.ts b/webui/src/app/components/health/health.component.ts
deleted file mode 100644
index ff290fa16..000000000
--- a/webui/src/app/components/health/health.component.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { Component, OnDestroy, OnInit } from '@angular/core';
-import { distanceInWordsStrict, format, subSeconds } from 'date-fns';
-import * as _ from 'lodash';
-import { Subscription, timer } from 'rxjs';
-import { mergeMap, timeInterval } from 'rxjs/operators';
-import { ApiService } from '../../services/api.service';
-
-@Component({
- selector: 'app-health',
- templateUrl: 'health.component.html'
-})
-export class HealthComponent implements OnInit, OnDestroy {
- sub: Subscription;
- recentErrors: any;
- previousRecentErrors: any;
- pid: number;
- uptime: string;
- uptimeSince: string;
- averageResponseTime: string;
- exactAverageResponseTime: string;
- totalResponseTime: string;
- exactTotalResponseTime: string;
- codeCount: number;
- totalCodeCount: number;
- chartValue: any;
- statusCodeValue: any;
-
- constructor(private apiService: ApiService) {}
-
- ngOnInit() {
- this.sub = timer(0, 3000)
- .pipe(
- timeInterval(),
- mergeMap(() => this.apiService.fetchHealthStatus())
- )
- .subscribe(data => {
- if (data) {
- if (!_.isEqual(this.previousRecentErrors, data.recent_errors)) {
- this.previousRecentErrors = _.cloneDeep(data.recent_errors);
- this.recentErrors = data.recent_errors;
- }
-
- this.chartValue = {
- count: data.average_response_time_sec,
- date: data.time
- };
- this.statusCodeValue = Object.keys(data.total_status_code_count).map(
- key => ({ code: key, count: data.total_status_code_count[key] })
- );
-
- this.pid = data.pid;
- this.uptime = distanceInWordsStrict(
- subSeconds(new Date(), data.uptime_sec),
- new Date()
- );
- this.uptimeSince = format(
- subSeconds(new Date(), data.uptime_sec),
- 'YYYY-MM-DD HH:mm:ss Z'
- );
- this.totalResponseTime = distanceInWordsStrict(
- subSeconds(new Date(), data.total_response_time_sec),
- new Date()
- );
- this.exactTotalResponseTime = data.total_response_time;
- this.averageResponseTime =
- Math.floor(data.average_response_time_sec * 1000) + ' ms';
- this.exactAverageResponseTime = data.average_response_time;
- this.codeCount = data.count;
- this.totalCodeCount = data.total_count;
- }
- });
- }
-
- ngOnDestroy() {
- if (this.sub) {
- this.sub.unsubscribe();
- }
- }
-
- trackRecentErrors(index, item): string {
- return item.status_code + item.method + item.host + item.path + item.time;
- }
-}
diff --git a/webui/src/app/components/providers/providers.component.html b/webui/src/app/components/providers/providers.component.html
deleted file mode 100644
index ab243adf0..000000000
--- a/webui/src/app/components/providers/providers.component.html
+++ /dev/null
@@ -1,1289 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ frontends.length }}Frontends
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Route Rule
-
-
-
-
-
- {{ route.rule }}
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{
- p.backend
- }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Priority
- {{
- p.priority
- }}
-
-
-
-
- Host Header
- {{
- !!p.passHostHeader
- }}
-
-
-
-
- TLS Cert
- {{
- p.passTLSCert
- }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{
- p.redirect.permanent
- ? 'Permanent'
- : 'Temporary'
- }}
- to
- {{
- p.redirect.entryPoint
- }}
-
-
-
-
-
- {{
- p.redirect.permanent
- ? 'Permanent'
- : 'Temporary'
- }}
-
-
- From
- {{
- p.redirect.regex
- }}
-
-
- To
- {{
- p.redirect.replacement
- }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Users File
- |
-
- {{
- p.auth.basic.usersFile
- }}
- |
-
-
-
- Header Field
- |
-
- {{
- p.auth.headerField
- }}
- |
-
-
-
- Remove Auth Header
- |
-
- {{
- !!p.auth.basic.removeHeader
- }}
- |
-
-
-
- Users
- |
-
-
- {{
- user
- }}
-
- |
-
-
-
-
-
-
-
-
-
-
- Users File
- |
-
- {{
- p.auth.digest.usersFile
- }}
- |
-
-
-
- Header Field
- |
-
- {{
- p.auth.headerField
- }}
- |
-
-
-
- Remove Auth Header
- |
-
- {{
- !!p.auth.digest.removeHeader
- }}
- |
-
-
-
- Users
- |
-
-
- {{
- user
- }}
-
- |
-
-
-
-
-
-
-
-
-
-
- Address
- |
-
- {{
- p.auth.forward.address
- }}
- |
-
-
-
- Trust Forward Header
- |
-
- {{
- p.auth.forward.trustForwardHeader
- }}
- |
-
-
-
- Response Headers
- |
-
-
- {{
- respHeader
- }}
-
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Backend |
- Query |
- Status |
-
-
-
- {{
- entry.backend
- }}
- |
-
- {{
- entry.query
- }}
- |
-
- {{ state }}
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- useXForwardedFor
- {{
- !!p.whiteList.useXForwardedFor
- }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Custom Request Headers |
-
-
-
- {{
- header.name
- }}
- |
-
- {{
- header.value
- }}
- |
-
-
-
-
-
-
-
-
-
- Custom Response Headers |
-
-
-
- {{
- header.name
- }}
- |
-
- {{
- header.value
- }}
- |
-
-
-
-
-
-
-
-
-
- Secure |
-
-
-
- Browser XSS Filter
- |
-
- {{
- p.headers.browserXssFilter
- }}
- |
-
-
-
- Content Security Policy
- |
-
- {{
- p.headers.contentSecurityPolicy
- }}
- |
-
-
-
- Content Type (No sniff)
- |
-
- {{
- p.headers.contentTypeNoSniff
- }}
- |
-
-
-
- Custom Frame Options Value
- |
-
- {{
- p.headers.customFrameOptionsValue
- }}
- |
-
-
-
- Force STS Header
- |
-
- {{
- p.headers.forceSTSHeader
- }}
- |
-
-
-
- Frame Deny
- |
-
- {{
- p.headers.frameDeny
- }}
- |
-
-
-
- Is Development
- |
-
- {{
- p.headers.isDevelopment
- }}
- |
-
-
-
- Public Key
- |
-
- {{
- p.headers.publicKey
- }}
- |
-
-
-
- Referrer Policy
- |
-
- {{
- p.headers.referrerPolicy
- }}
- |
-
-
-
- SSL Host
- |
-
- {{
- p.headers.sslHost
- }}
- |
-
-
-
- SSL Force Host
- |
-
- {{
- p.headers.sslForceHost
- }}
- |
-
-
-
- SSL Redirect
- |
-
- {{
- p.headers.sslRedirect
- }}
- |
-
-
-
- SSL Temporary Redirect
- |
-
- {{
- p.headers.sslTemporaryRedirect
- }}
- |
-
-
-
- STS Include Subdomains
- |
-
- {{
- p.headers.stsIncludeSubdomains
- }}
- |
-
-
-
- STS Preload
- |
-
- {{
- p.headers.stsPreload
- }}
- |
-
-
-
- STS Seconds
- |
-
- {{
- p.headers.stsSeconds
- }}
- |
-
-
-
-
-
-
-
-
-
- SSL Proxy Headers |
-
-
-
- {{
- header.name
- }}
- |
-
- {{
- header.value
- }}
- |
-
-
-
-
-
-
-
Allowed Hosts
-
- {{ host }}
-
-
-
-
-
Hosts Proxy Headers
-
- {{ h }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Extractor Function
- {{
- p.ratelimit.extractorFunc
- }}
-
-
-
-
- Rateset |
- Period |
- Average |
- Burst |
-
-
-
- {{ rateset.id }} |
-
- {{ rateset.period | humanreadable }}
- |
- {{ rateset.average }} |
- {{ rateset.burst }} |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ backends.length }}Backends
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Server |
- Weight |
-
-
-
- {{ server.url }}
- |
-
- {{
- server.weight
- }}
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Method
- {{
- p.loadBalancer.method
- }}
-
-
-
-
- Stickiness
- true
-
-
-
-
- Cookie Name
- {{
- p.loadBalancer.stickiness.cookieName
- }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Amount
- {{
- p.maxConn.amount
- }}
-
-
-
-
- Extractor Function
- {{
- p.maxConn.extractorFunc
- }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Expression
- {{
- p.circuitBreaker.expression
- }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Path
- {{
- p.healthCheck.path
- }}
-
-
-
-
- Interval
- {{
- p.healthCheck.interval
- }}
-
-
-
-
- Timeout
- {{
- p.healthCheck.timeout
- }}
-
-
-
-
- Port
- {{
- p.healthCheck.port
- }}
-
-
-
-
- Scheme
- {{
- p.healthCheck.scheme
- }}
-
-
-
-
- Hostname
- {{
- p.healthCheck.hostname
- }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Request Body Bytes
- |
-
-
-
-
- Max
- {{
- p.buffering.maxRequestBodyBytes
- }}
-
-
-
- |
-
-
-
-
- Mem
- {{
- p.buffering.memRequestBodyBytes
- }}
-
-
-
- |
-
-
-
- Response Body Bytes
- |
-
-
-
-
- Max
- {{
- p.buffering.maxResponseBodyBytes
- }}
-
-
-
- |
-
-
-
-
- Mem
- {{
- p.buffering.memResponseBodyBytes
- }}
-
-
-
- |
-
-
- Retry Expression |
-
- {{
- p.buffering.retryExpression
- }}
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- No providers found.
-
-
-
-
-
diff --git a/webui/src/app/components/providers/providers.component.ts b/webui/src/app/components/providers/providers.component.ts
deleted file mode 100644
index 37790bf20..000000000
--- a/webui/src/app/components/providers/providers.component.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { Component, OnDestroy, OnInit } from '@angular/core';
-import * as _ from 'lodash';
-import { Subscription, timer } from 'rxjs';
-import { mergeMap, timeInterval } from 'rxjs/operators';
-import { ApiService } from '../../services/api.service';
-
-@Component({
- selector: 'app-providers',
- templateUrl: 'providers.component.html'
-})
-export class ProvidersComponent implements OnInit, OnDestroy {
- sub: Subscription;
- maxItem: number;
- keys: string[];
- previousKeys: string[];
- previousData: any;
- providers: any;
- tab: string;
- keyword: string;
-
- constructor(private apiService: ApiService) {}
-
- ngOnInit() {
- this.maxItem = 100;
- this.keyword = '';
- this.sub = timer(0, 2000)
- .pipe(
- timeInterval(),
- mergeMap(() => this.apiService.fetchProviders())
- )
- .subscribe(data => {
- if (!_.isEqual(this.previousData, data)) {
- this.previousData = _.cloneDeep(data);
- this.providers = data;
-
- const keys = Object.keys(this.providers);
- if (!_.isEqual(this.previousKeys, keys)) {
- this.keys = keys;
-
- // keep current tab or set to the first tab
- if (!this.tab || (this.tab && !this.keys.includes(this.tab))) {
- this.tab = this.keys[0];
- }
- }
- }
- });
- }
-
- trackItem(tab): (index, item) => string {
- return (index, item): string => tab + '-' + item.id;
- }
-
- ngOnDestroy() {
- if (this.sub) {
- this.sub.unsubscribe();
- }
- }
-}
diff --git a/webui/src/app/directives/let.directive.ts b/webui/src/app/directives/let.directive.ts
deleted file mode 100644
index 36c827501..000000000
--- a/webui/src/app/directives/let.directive.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
-
-interface LetContext {
- appLet: T;
-}
-
-@Directive({
- selector: '[appLet]'
-})
-export class LetDirective {
- private _context: LetContext = { appLet: null };
-
- constructor(
- _viewContainer: ViewContainerRef,
- _templateRef: TemplateRef>
- ) {
- _viewContainer.createEmbeddedView(_templateRef, this._context);
- }
-
- @Input()
- set appLet(value: T) {
- this._context.appLet = value;
- }
-}
diff --git a/webui/src/app/pipes/backend.filter.pipe.ts b/webui/src/app/pipes/backend.filter.pipe.ts
deleted file mode 100644
index 0eb0debeb..000000000
--- a/webui/src/app/pipes/backend.filter.pipe.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { Pipe, PipeTransform } from '@angular/core';
-
-@Pipe({
- name: 'backendFilter',
- pure: false
-})
-export class BackendFilterPipe implements PipeTransform {
- transform(items: any[], filter: string): any {
- if (!items || !filter) {
- return items;
- }
-
- const keyword = filter.toLowerCase();
- return items.filter(
- d =>
- d.id.toLowerCase().includes(keyword) ||
- d.servers.some(r => r.url.toLowerCase().includes(keyword))
- );
- }
-}
diff --git a/webui/src/app/pipes/frontend.filter.pipe.ts b/webui/src/app/pipes/frontend.filter.pipe.ts
deleted file mode 100644
index 566c635bc..000000000
--- a/webui/src/app/pipes/frontend.filter.pipe.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Pipe, PipeTransform } from '@angular/core';
-
-@Pipe({
- name: 'frontendFilter',
- pure: false
-})
-export class FrontendFilterPipe implements PipeTransform {
- transform(items: any[], filter: string): any {
- if (!items || !filter) {
- return items;
- }
-
- const keyword = filter.toLowerCase();
- return items.filter(
- d =>
- d.id.toLowerCase().includes(keyword) ||
- d.backend.toLowerCase().includes(keyword) ||
- d.routes.some(r => r.rule.toLowerCase().includes(keyword))
- );
- }
-}
diff --git a/webui/src/app/pipes/humanreadable.filter.pipe.spec.ts b/webui/src/app/pipes/humanreadable.filter.pipe.spec.ts
deleted file mode 100644
index 40e990136..000000000
--- a/webui/src/app/pipes/humanreadable.filter.pipe.spec.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { HumanReadableFilterPipe } from './humanreadable.filter.pipe';
-
-describe('HumanReadableFilterPipe', () => {
- const pipe = new HumanReadableFilterPipe();
-
- const datatable = [
- {
- given: '180000000000',
- expected: '180s'
- },
- {
- given: '4096.0',
- expected: '4096ns'
- },
- {
- given: '7200000000000',
- expected: '120m'
- },
- {
- given: '1337',
- expected: '1337ns'
- },
- {
- given: 'traefik',
- expected: 'traefik'
- },
- {
- given: '-23',
- expected: '-23'
- },
- {
- given: '0',
- expected: '0'
- }
- ];
-
- datatable.forEach(item => {
- it(item.given + ' should be transformed to ' + item.expected, () => {
- expect(pipe.transform(item.given)).toEqual(item.expected);
- });
- });
-
- it('create an instance', () => {
- expect(pipe).toBeTruthy();
- });
-});
diff --git a/webui/src/app/pipes/humanreadable.filter.pipe.ts b/webui/src/app/pipes/humanreadable.filter.pipe.ts
deleted file mode 100644
index 0dac2895b..000000000
--- a/webui/src/app/pipes/humanreadable.filter.pipe.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { Pipe, PipeTransform } from '@angular/core';
-
-/**
- * HumanReadableFilterPipe converts a time period in nanoseconds to a human-readable
- * string.
- */
-@Pipe({ name: 'humanreadable' })
-export class HumanReadableFilterPipe implements PipeTransform {
- transform(value): any {
- let result = '';
- const powerOf10 = Math.floor(Math.log10(value));
-
- if (powerOf10 > 11) {
- result = value / (60 * Math.pow(10, 9)) + 'm';
- } else if (powerOf10 > 9) {
- result = value / Math.pow(10, 9) + 's';
- } else if (powerOf10 > 6) {
- result = value / Math.pow(10, 6) + 'ms';
- } else if (value > 0) {
- result = Math.floor(value) + 'ns';
- } else {
- result = value;
- }
-
- return result;
- }
-}
diff --git a/webui/src/app/pipes/keys.pipe.ts b/webui/src/app/pipes/keys.pipe.ts
deleted file mode 100644
index 0429745a2..000000000
--- a/webui/src/app/pipes/keys.pipe.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { Pipe, PipeTransform } from '@angular/core';
-
-@Pipe({ name: 'keys' })
-export class KeysPipe implements PipeTransform {
- transform(value, args: string[]): any {
- return Object.keys(value);
- }
-}
diff --git a/webui/src/app/services/api.service.ts b/webui/src/app/services/api.service.ts
deleted file mode 100644
index 4cf518afa..000000000
--- a/webui/src/app/services/api.service.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-import {
- HttpClient,
- HttpErrorResponse,
- HttpHeaders
-} from '@angular/common/http';
-import { Injectable } from '@angular/core';
-import { Observable, EMPTY, of } from 'rxjs';
-import { catchError, map, retry } from 'rxjs/operators';
-
-export interface ProviderType {
- [provider: string]: {
- backends: any;
- frontends: any;
- };
-}
-
-@Injectable()
-export class ApiService {
- headers: HttpHeaders;
-
- constructor(private http: HttpClient) {
- this.headers = new HttpHeaders({
- 'Access-Control-Allow-Origin': '*'
- });
- }
-
- fetchVersion(): Observable {
- return this.http.get('../api/version', { headers: this.headers }).pipe(
- retry(4),
- catchError((err: HttpErrorResponse) => {
- console.error(
- `[version] returned code ${err.status}, body was: ${err.error}`
- );
- return EMPTY;
- })
- );
- }
-
- fetchHealthStatus(): Observable {
- return this.http.get('../health', { headers: this.headers }).pipe(
- retry(2),
- catchError((err: HttpErrorResponse) => {
- console.error(
- `[health] returned code ${err.status}, body was: ${err.error}`
- );
- return EMPTY;
- })
- );
- }
-
- fetchProviders(): Observable {
- return this.http.get('../api/providers', { headers: this.headers }).pipe(
- retry(2),
- catchError((err: HttpErrorResponse) => {
- console.error(
- `[providers] returned code ${err.status}, body was: ${err.error}`
- );
- return of({});
- }),
- map((data: any): ProviderType => this.parseProviders(data))
- );
- }
-
- parseProviders(data: any): ProviderType {
- return Object.keys(data)
- .filter(value => value !== 'acme' && value !== 'ACME')
- .reduce((acc, curr) => {
- acc[curr] = {};
-
- acc[curr].frontends = this.toArray(data[curr].frontends, 'id').map(
- frontend => {
- frontend.routes = this.toArray(frontend.routes, 'id');
- frontend.errors = this.toArray(frontend.errors, 'id');
- if (frontend.headers) {
- frontend.headers.customRequestHeaders = this.toHeaderArray(
- frontend.headers.customRequestHeaders
- );
- frontend.headers.customResponseHeaders = this.toHeaderArray(
- frontend.headers.customResponseHeaders
- );
- frontend.headers.sslProxyHeaders = this.toHeaderArray(
- frontend.headers.sslProxyHeaders
- );
- }
- if (frontend.ratelimit && frontend.ratelimit.rateset) {
- frontend.ratelimit.rateset = this.toArray(
- frontend.ratelimit.rateset,
- 'id'
- );
- }
- return frontend;
- }
- );
-
- acc[curr].backends = this.toArray(data[curr].backends, 'id').map(
- backend => {
- backend.servers = this.toArray(backend.servers, 'id');
- return backend;
- }
- );
-
- return acc;
- }, {});
- }
-
- toHeaderArray(data: any): any[] {
- return Object.keys(data || {}).map(key => ({
- name: key,
- value: data[key]
- }));
- }
-
- toArray(data: any, fieldKeyName: string): any[] {
- return Object.keys(data || {}).map(key => {
- data[key][fieldKeyName] = key;
- return data[key];
- });
- }
-}
diff --git a/webui/src/app/services/window.service.ts b/webui/src/app/services/window.service.ts
deleted file mode 100644
index b54e993e5..000000000
--- a/webui/src/app/services/window.service.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Injectable } from '@angular/core';
-import { EventManager } from '@angular/platform-browser';
-import { Subject } from 'rxjs';
-
-@Injectable()
-export class WindowService {
- resize: Subject;
-
- constructor(private eventManager: EventManager) {
- this.resize = new Subject();
- this.eventManager.addGlobalEventListener(
- 'window',
- 'resize',
- (event: UIEvent) => {
- this.resize.next(event.target);
- }
- );
- }
-}