Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
A
assignment1
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Mathilde Hertaas
assignment1
Commits
d62941f3
Commit
d62941f3
authored
2 months ago
by
Mathilde Hertaas
Browse files
Options
Downloads
Patches
Plain Diff
cities is now included in info endpoint, user can spesify but not over 10
parent
06a502b9
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
main.go
+195
-69
195 additions, 69 deletions
main.go
with
195 additions
and
69 deletions
main.go
+
195
−
69
View file @
d62941f3
...
...
@@ -4,132 +4,258 @@ import (
"encoding/json"
"fmt"
"net/http"
"time"
"strings"
"strconv"
)
//countryinfo/v1/info/{country_code}{?limit=10}
//given country, 2-letter country codes (ISO 3166-2).
//limit is the number of cities that are listed in the response.
var
serviceStartTime
time
.
Time
// Struktur for å lagre data om landene i info endepunktet
// Funksjon for å hente statuskode fra et API
func
getAPIStatus
(
url
string
)
(
int
,
error
)
{
resp
,
err
:=
http
.
Get
(
url
)
if
err
!=
nil
{
return
0
,
err
}
defer
resp
.
Body
.
Close
()
// Returner HTTP-statuskoden
return
resp
.
StatusCode
,
nil
}
// Funksjon for å beregne oppetid
func
getUptime
()
int64
{
return
int64
(
time
.
Since
(
serviceStartTime
)
.
Seconds
())
}
// Handler for Diagnostics endpoint
func
diagnosticsHandler
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
// Hent statuskoder fra eksterne API-er
countriesNowStatus
,
err
:=
getAPIStatus
(
"http://129.241.150.113:3500/api/v0.1/countries"
)
if
err
!=
nil
{
http
.
Error
(
w
,
"Error fetching CountriesNow status"
,
http
.
StatusInternalServerError
)
return
}
restCountriesStatus
,
err
:=
getAPIStatus
(
"http://129.241.150.113:8080/v3.1/all"
)
//funker med all
if
err
!=
nil
{
http
.
Error
(
w
,
"Error fetching RestCountries status"
,
http
.
StatusInternalServerError
)
return
}
// Bygg responsen med statusinformasjon
response
:=
map
[
string
]
interface
{}{
"countriesnowapi"
:
fmt
.
Sprintf
(
"%d"
,
countriesNowStatus
),
"restcountriesapi"
:
fmt
.
Sprintf
(
"%d"
,
restCountriesStatus
),
"version"
:
"v1"
,
// Versjon av API
"uptime"
:
getUptime
(),
// Oppetid i sekunder
}
// Sett Content-Type til application/json
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
// Returner JSON-responsen
json
.
NewEncoder
(
w
)
.
Encode
(
response
)
}
type
Flags
struct
{
PNG
string
`json:"png"`
}
// Struktur for data fra REST Countries API
type
CountryInfo
struct
{
Name
struct
{
Common
string
`json:"common"`
Official
string
`json:"official"`
}
`json:"name"`
Capital
[]
string
`json:"capital"`
Region
string
`json:"region"`
Common
string
`json:"common"`
Official
string
`json:"official"`
}
`json:"name"`
Capital
[]
string
`json:"capital"`
Languages
map
[
string
]
string
`json:"languages"`
Continents
[]
string
`json:"continents"`
Borders
[]
string
`json:"borders"`
Population
int
`json:"population"`
Flags
Flags
`json:"flags"`
}
type
CityInfo
struct
{
Cities
[]
string
`json:"cities"`
}
//Når du kjører koden blir du sendt til en hjemmeside siden forespørsel spesifikasjoner ikke er gitt enda
//info om hvordan bruke API
func
homeHandler
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
// Strukturert respons for bedre lesbarhet
response
:=
map
[
string
]
interface
{}{
"WELCOME"
:
"Welcome to the Country Info API"
,
"endpoints"
:
map
[
string
]
interface
{}{
"Endpoint 1"
:
map
[
string
]
string
{
"Description"
:
"Get information about a country using its ISO 3166-1 alpha-2 code."
,
"URL"
:
"http://localhost:8080/countryinfo/v1/info/{country_code}{?limit=10}"
,
"Example"
:
"http://localhost:8080/countryinfo/v1/info/NO"
,
},
"Endpoint 2"
:
map
[
string
]
interface
{}{
"Description"
:
"TO BE IMPLEMENTED"
,
},
},
}
json
.
NewEncoder
(
w
)
.
Encode
(
response
)
}
// Struktur for kombinert respons
type
CombinedInfo
struct
{
Name
string
`json:"name"`
Continents
[]
string
`json:"continenents"`
Population
int
`json:"population"`
Languages
map
[
string
]
string
`json:"languages"`
Borders
[]
string
`json:"borders"`
Flags
string
`json:"flags"`
Capital
string
`json:"capital"`
Cities
string
`json:"cities"`
}
//
En funksjon som h
enter data fra
det eksterne API-et ved landkode
//
H
enter
land
data fra
REST Countries API
func
getCountryDataByCode
(
countryCode
string
)
(
*
CountryInfo
,
error
)
{
//bygge en URL for API kallet
url
:=
fmt
.
Sprintf
(
"http://129.241.150.113:8080/v3.1/alpha/%s"
,
countryCode
)
//sender en http forespørsel
resp
,
err
:=
http
.
Get
(
url
)
if
err
!=
nil
{
return
nil
,
err
}
defer
resp
.
Body
.
Close
()
// Sjekk om API-kallet var vellykket (statuskode 200)
if
resp
.
StatusCode
!=
http
.
StatusOK
{
return
nil
,
fmt
.
Errorf
(
"error retrieving country data, status code: %d"
,
resp
.
StatusCode
)
}
// Håndterer en http feil, som om landet ikke finnes
var
countries
[]
CountryInfo
if
err
:=
json
.
NewDecoder
(
resp
.
Body
)
.
Decode
(
&
countries
);
err
!=
nil
{
return
nil
,
err
}
// Hvis vi ikke får noen treff
if
len
(
countries
)
==
0
{
return
nil
,
fmt
.
Errorf
(
"country not found for code: %s"
,
countryCode
)
}
// Returner det første elementet i listen siden forventer bare ett treff)
return
&
countries
[
0
],
nil
}
func
getCitiesByCountry
(
countryName
string
)
([]
string
,
error
)
{
url
:=
fmt
.
Sprintf
(
"https://countriesnow.space/api/v0.1/countries/cities/q?country=%s"
,
countryName
)
resp
,
err
:=
http
.
Get
(
url
)
if
err
!=
nil
{
return
nil
,
err
}
defer
resp
.
Body
.
Close
()
//oprett en handler for /countryinfo/v1/info/{country_code}
// leser landkoden fra URL
// slår opp dataene
// REturnerer dem som JSON
func
handler
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
// Hent landkode fra path
if
resp
.
StatusCode
!=
http
.
StatusOK
{
return
nil
,
fmt
.
Errorf
(
"error retrieving cities, status code: %d"
,
resp
.
StatusCode
)
}
var
responseBody
map
[
string
]
interface
{}
if
err
:=
json
.
NewDecoder
(
resp
.
Body
)
.
Decode
(
&
responseBody
);
err
!=
nil
{
return
nil
,
err
}
if
cities
,
ok
:=
responseBody
[
"data"
]
.
([]
interface
{});
ok
{
var
cityList
[]
string
for
_
,
city
:=
range
cities
{
if
cityStr
,
ok
:=
city
.
(
string
);
ok
{
cityList
=
append
(
cityList
,
cityStr
)
}
}
// Hvis ingen byer er funnet, returner en feilmelding
if
len
(
cityList
)
==
0
{
fmt
.
Println
(
"No cities found in the response."
)
}
return
cityList
,
nil
}
return
nil
,
fmt
.
Errorf
(
"no cities found for country %s"
,
countryName
)
}
func
countryInfoHandler
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
parts
:=
strings
.
Split
(
r
.
URL
.
Path
,
"/"
)
if
len
(
parts
)
<
5
{
http
.
Error
(
w
,
"Invalid format.
Please use the format
/countryinfo/v1/info/{countryCode}
{?limit=10}. Example: /countryinfo/v1/info/NO
"
,
http
.
StatusBadRequest
)
http
.
Error
(
w
,
"Invalid format.
Use:
/countryinfo/v1/info/{countryCode}"
,
http
.
StatusBadRequest
)
return
}
countryCode
:=
parts
[
4
]
// Landkoden er den 5. delen av pathen (fra 0)
countryCode
:=
parts
[
4
]
// Hent data fra API ved landkode
//country inneholder data om alt går bra
// Hent landdata fra REST Countries API
country
,
err
:=
getCountryDataByCode
(
countryCode
)
//err inneholder feil hvis noe går galt, ikke finner landkode
if
err
!=
nil
{
http
.
Error
(
w
,
fmt
.
Sprintf
(
"Error retrieving data for country code: %s. Check if the country code is correct.
\n
Example: /countryinfo/v1/info/NO
\n
Error: %s"
,
countryCode
,
err
.
Error
(),
),
http
.
StatusInternalServerError
)
http
.
Error
(
w
,
err
.
Error
(),
http
.
StatusInternalServerError
)
return
}
// Hent antall byer som skal vises fra URL-parameteren (default til 10)
// F.eks. /countryinfo/v1/info/NO?cities=5
cityCount
:=
10
// Standardverdi
cityCountStr
:=
r
.
URL
.
Query
()
.
Get
(
"cities"
)
// Hent "cities" parameteren
if
cityCountStr
!=
""
{
// Prøv å konvertere parameteren til et heltall
if
count
,
err
:=
strconv
.
Atoi
(
cityCountStr
);
err
==
nil
&&
count
>
0
{
cityCount
=
count
}
}
// Hent byene fra countriesnow API
cities
,
err
:=
getCitiesByCountry
(
country
.
Name
.
Common
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
http
.
StatusInternalServerError
)
return
}
// Hvis det er flere enn det brukeren ønsker, begrens listen
if
len
(
cities
)
>
cityCount
{
cities
=
cities
[
:
cityCount
]
}
// Feilsøking: Hvis ingen byer ble funnet
if
len
(
cities
)
==
0
{
fmt
.
Printf
(
"No cities found for %s
\n
"
,
country
.
Name
.
Common
)
}
// Returner JSON-respons
// Begrens byene til maks 10
if
len
(
cities
)
>
10
{
cities
=
cities
[
:
10
]
}
// Bygg kombinert respons
response
:=
CombinedInfo
{
Name
:
country
.
Name
.
Common
,
Continents
:
country
.
Continents
,
Population
:
country
.
Population
,
Languages
:
country
.
Languages
,
Borders
:
country
.
Borders
,
Flags
:
country
.
Flags
.
PNG
,
Capital
:
""
,
Cities
:
strings
.
Join
(
cities
,
", "
),
// Legg til de 10 første byene som en kommaseparert liste
}
if
len
(
country
.
Capital
)
>
0
{
response
.
Capital
=
country
.
Capital
[
0
]
}
// Sett Content-Type til application/json
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
json
.
NewEncoder
(
w
)
.
Encode
(
country
)
json
.
NewEncoder
(
w
)
.
Encode
(
response
)
}
// kaller de ulike funkjsonene basert på hvilken URL som sender forespørsel
func
main
()
{
http
.
HandleFunc
(
"/"
,
homeHandler
)
//Rute for info om land
http
.
HandleFunc
(
"/countryinfo/v1/info/"
,
handler
)
//starttidspunkt for tjenesten
serviceStartTime
=
time
.
Now
()
http
.
HandleFunc
(
"/status/"
,
diagnosticsHandler
)
http
.
HandleFunc
(
"/"
,
homeHandler
)
http
.
HandleFunc
(
"/countryinfo/v1/info/"
,
countryInfoHandler
)
//info i terminal
fmt
.
Println
(
"Server running on port 8080..."
)
if
err
:=
http
.
ListenAndServe
(
":8080"
,
nil
);
err
!=
nil
{
// Logg feilen og avslutt programmet dersom serveren ikke kan starte
fmt
.
Printf
(
"Server failed to start: %s
\n
"
,
err
)
}
}
//URL for å teste info for norge
//http://localhost:8080/countryinfo/v1/info/No
\ No newline at end of file
func
homeHandler
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
response
:=
map
[
string
]
interface
{}{
"WELCOME"
:
"Welcome to the Country Info API"
,
"endpoints"
:
map
[
string
]
interface
{}{
"Get Country Info"
:
map
[
string
]
string
{
"Description"
:
"Get country details including cities, population, and more."
,
"URL Format"
:
"http://localhost:8080/countryinfo/v1/info/{country_code}{?limit=10}"
,
"Example"
:
"http://localhost:8080/countryinfo/v1/info/NO?cities=5"
,
},
"Get status info"
:
map
[
string
]
string
{
"Description"
:
"Get information about the API statuses"
,
"URL"
:
"http://localhost:8080/status/"
,
},
},
}
json
.
NewEncoder
(
w
)
.
Encode
(
response
)
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment