Browse Source

Bugfix/encode symbols with special characters in API request urls (#7110)

* Encode symbols in API request urls

* Update changelog
pull/7107/head
Thomas Kaul 5 days ago
committed by GitHub
parent
commit
f53998f071
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 6
      apps/client/src/app/pages/api/api-page.component.ts
  3. 14
      libs/ui/src/lib/services/admin.service.ts
  4. 49
      libs/ui/src/lib/services/data.service.ts

1
CHANGELOG.md

@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Fixed an issue where symbols with special characters caused API request failures by URL encoding the symbol
- Fixed the disabled state of the delete action in the asset profiles actions menu of the historical market data table in the admin control panel
- Fixed the persistence of an empty `locale` string in the scraper configuration

6
apps/client/src/app/pages/api/api-page.component.ts

@ -94,7 +94,7 @@ export class GfApiPageComponent implements OnInit {
private fetchAssetProfile({ symbol }: { symbol: string }) {
return this.http
.get<DataProviderGhostfolioAssetProfileResponse>(
`/api/v1/data-providers/ghostfolio/asset-profile/${symbol}`,
`/api/v1/data-providers/ghostfolio/asset-profile/${encodeURIComponent(symbol)}`,
{ headers: this.getHeaders() }
)
.pipe(this.catchFetchFailure(), takeUntilDestroyed(this.destroyRef));
@ -107,7 +107,7 @@ export class GfApiPageComponent implements OnInit {
return this.http
.get<DividendsResponse>(
`/api/v2/data-providers/ghostfolio/dividends/${symbol}`,
`/api/v2/data-providers/ghostfolio/dividends/${encodeURIComponent(symbol)}`,
{
params,
headers: this.getHeaders()
@ -129,7 +129,7 @@ export class GfApiPageComponent implements OnInit {
return this.http
.get<HistoricalResponse>(
`/api/v2/data-providers/ghostfolio/historical/${symbol}`,
`/api/v2/data-providers/ghostfolio/historical/${encodeURIComponent(symbol)}`,
{
params,
headers: this.getHeaders()

14
libs/ui/src/lib/services/admin.service.ts

@ -36,7 +36,7 @@ export class AdminService {
public addAssetProfile({ dataSource, symbol }: AssetProfileIdentifier) {
return this.http.post<void>(
`/api/v1/admin/profile-data/${dataSource}/${symbol}`,
`/api/v1/admin/profile-data/${dataSource}/${encodeURIComponent(symbol)}`,
null
);
}
@ -63,7 +63,7 @@ export class AdminService {
public deleteProfileData({ dataSource, symbol }: AssetProfileIdentifier) {
return this.http.delete<void>(
`/api/v1/admin/profile-data/${dataSource}/${symbol}`
`/api/v1/admin/profile-data/${dataSource}/${encodeURIComponent(symbol)}`
);
}
@ -140,7 +140,7 @@ export class AdminService {
symbol
}: AssetProfileIdentifier) {
return this.http.post<void>(
`/api/v1/admin/gather/profile-data/${dataSource}/${symbol}`,
`/api/v1/admin/gather/profile-data/${dataSource}/${encodeURIComponent(symbol)}`,
{}
);
}
@ -162,7 +162,7 @@ export class AdminService {
params = params.append('range', range);
}
const url = `/api/v1/admin/gather/${dataSource}/${symbol}`;
const url = `/api/v1/admin/gather/${dataSource}/${encodeURIComponent(symbol)}`;
return this.http.post<MarketData | void>(url, undefined, { params });
}
@ -172,7 +172,7 @@ export class AdminService {
dateString,
symbol
}: { dateString: string } & AssetProfileIdentifier) {
const url = `/api/v1/symbol/${dataSource}/${symbol}/${dateString}`;
const url = `/api/v1/symbol/${dataSource}/${encodeURIComponent(symbol)}/${dateString}`;
return this.http.get<DataProviderHistoricalResponse>(url);
}
@ -197,7 +197,7 @@ export class AdminService {
}: UpdateAssetProfileDto
) {
return this.http.patch<EnhancedSymbolProfile>(
`/api/v1/admin/profile-data/${dataSource}/${symbol}`,
`/api/v1/admin/profile-data/${dataSource}/${encodeURIComponent(symbol)}`,
{
assetClass,
assetSubClass,
@ -238,7 +238,7 @@ export class AdminService {
symbol
}: AssetProfileIdentifier & UpdateAssetProfileDto['scraperConfiguration']) {
return this.http.post<{ price: number }>(
`/api/v1/admin/market-data/${dataSource}/${symbol}/test`,
`/api/v1/admin/market-data/${dataSource}/${encodeURIComponent(symbol)}/test`,
{
scraperConfiguration
}

49
libs/ui/src/lib/services/data.service.ts

@ -301,7 +301,7 @@ export class DataService {
public fetchDividendsImport({ dataSource, symbol }: AssetProfileIdentifier) {
return this.http.get<ImportResponse>(
`/api/v1/import/dividends/${dataSource}/${symbol}`
`/api/v1/import/dividends/${dataSource}/${encodeURIComponent(symbol)}`
);
}
@ -313,7 +313,7 @@ export class DataService {
symbol: string;
}) {
return this.http.get<DataProviderHistoricalResponse>(
`/api/v1/exchange-rate/${symbol}/${format(date, DATE_FORMAT, { in: utc })}`
`/api/v1/exchange-rate/${encodeURIComponent(symbol)}/${format(date, DATE_FORMAT, { in: utc })}`
);
}
@ -341,7 +341,7 @@ export class DataService {
public deleteBenchmark({ dataSource, symbol }: AssetProfileIdentifier) {
return this.http.delete<Partial<SymbolProfile>>(
`/api/v1/benchmarks/${dataSource}/${symbol}`
`/api/v1/benchmarks/${dataSource}/${encodeURIComponent(symbol)}`
);
}
@ -358,7 +358,9 @@ export class DataService {
}
public deleteWatchlistItem({ dataSource, symbol }: AssetProfileIdentifier) {
return this.http.delete<void>(`/api/v1/watchlist/${dataSource}/${symbol}`);
return this.http.delete<void>(
`/api/v1/watchlist/${dataSource}/${encodeURIComponent(symbol)}`
);
}
public fetchAccesses() {
@ -369,14 +371,16 @@ export class DataService {
dataSource,
symbol
}: AssetProfileIdentifier): Observable<AssetResponse> {
return this.http.get<any>(`/api/v1/asset/${dataSource}/${symbol}`).pipe(
map((data) => {
for (const item of data.marketData) {
item.date = parseISO(item.date);
}
return data;
})
);
return this.http
.get<any>(`/api/v1/asset/${dataSource}/${encodeURIComponent(symbol)}`)
.pipe(
map((data) => {
for (const item of data.marketData) {
item.date = parseISO(item.date);
}
return data;
})
);
}
public fetchAssetProfiles({
@ -437,7 +441,7 @@ export class DataService {
}
return this.http.get<BenchmarkMarketDataDetailsResponse>(
`/api/v1/benchmarks/${dataSource}/${symbol}/${format(startDate, DATE_FORMAT, { in: utc })}`,
`/api/v1/benchmarks/${dataSource}/${encodeURIComponent(symbol)}/${format(startDate, DATE_FORMAT, { in: utc })}`,
{ params }
);
}
@ -486,7 +490,7 @@ export class DataService {
> {
return this.http
.get<PortfolioHoldingResponse>(
`/api/v1/portfolio/holding/${dataSource}/${symbol}`
`/api/v1/portfolio/holding/${dataSource}/${encodeURIComponent(symbol)}`
)
.pipe(
map((response) => {
@ -540,7 +544,9 @@ export class DataService {
symbol
}: AssetProfileIdentifier): Observable<AssetProfileResponse> {
return this.http
.get<any>(`/api/v1/asset-profiles/${dataSource}/${symbol}`)
.get<any>(
`/api/v1/asset-profiles/${dataSource}/${encodeURIComponent(symbol)}`
)
.pipe(
map((data) => {
for (const item of data.marketData) {
@ -778,9 +784,12 @@ export class DataService {
params = params.append('includeHistoricalData', includeHistoricalData);
}
return this.http.get<SymbolItem>(`/api/v1/symbol/${dataSource}/${symbol}`, {
params
});
return this.http.get<SymbolItem>(
`/api/v1/symbol/${dataSource}/${encodeURIComponent(symbol)}`,
{
params
}
);
}
public fetchSymbols({
@ -851,7 +860,7 @@ export class DataService {
marketData,
symbol
}: { marketData: UpdateBulkMarketDataDto } & AssetProfileIdentifier) {
const url = `/api/v1/market-data/${dataSource}/${symbol}`;
const url = `/api/v1/market-data/${dataSource}/${encodeURIComponent(symbol)}`;
return this.http.post<MarketData>(url, marketData);
}
@ -890,7 +899,7 @@ export class DataService {
tags
}: { tags: Tag[] } & AssetProfileIdentifier) {
return this.http.put<void>(
`/api/v1/portfolio/holding/${dataSource}/${symbol}/tags`,
`/api/v1/portfolio/holding/${dataSource}/${encodeURIComponent(symbol)}/tags`,
{ tags }
);
}

Loading…
Cancel
Save