Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
G
GMS
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
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
IA2
GMS
Commits
fd37936e
Commit
fd37936e
authored
4 years ago
by
Sonia Zorba
Browse files
Options
Downloads
Patches
Plain Diff
RapClient error handling improvements
parent
dd8cfb0f
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
gms/src/main/java/it/inaf/ia2/gms/rap/RapClient.java
+29
-7
29 additions, 7 deletions
gms/src/main/java/it/inaf/ia2/gms/rap/RapClient.java
gms/src/test/java/it/inaf/ia2/gms/rap/RapClientTest.java
+153
-0
153 additions, 0 deletions
gms/src/test/java/it/inaf/ia2/gms/rap/RapClientTest.java
with
182 additions
and
7 deletions
gms/src/main/java/it/inaf/ia2/gms/rap/RapClient.java
+
29
−
7
View file @
fd37936e
package
it.inaf.ia2.gms.rap
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
it.inaf.ia2.gms.authn.SessionData
;
import
it.inaf.ia2.gms.model.RapUser
;
import
java.util.ArrayList
;
...
...
@@ -21,6 +23,8 @@ import org.springframework.stereotype.Component;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.web.client.HttpClientErrorException
;
import
org.springframework.web.client.HttpServerErrorException
;
import
org.springframework.web.client.HttpStatusCodeException
;
import
org.springframework.web.client.RestTemplate
;
@Component
...
...
@@ -51,6 +55,8 @@ public class RapClient {
private
final
RestTemplate
refreshTokenRestTemplate
;
private
final
ObjectMapper
objectMapper
=
new
ObjectMapper
();
@Autowired
public
RapClient
(
RestTemplate
rapRestTemplate
)
{
this
.
rapRestTemplate
=
rapRestTemplate
;
...
...
@@ -101,14 +107,30 @@ public class RapClient {
private
<
R
,
T
>
R
httpCall
(
Function
<
HttpEntity
<?>,
R
>
function
,
T
body
)
{
try
{
return
function
.
apply
(
getEntity
(
body
));
}
catch
(
HttpClientErrorException
.
Unauthorized
ex
)
{
if
(
request
.
getSession
(
false
)
==
null
)
{
// we can't refresh the token without a session
throw
ex
;
try
{
return
function
.
apply
(
getEntity
(
body
));
}
catch
(
HttpClientErrorException
.
Unauthorized
ex
)
{
if
(
request
.
getSession
(
false
)
==
null
||
sessionData
.
getExpiresIn
()
>
0
)
{
// we can't refresh the token without a session
throw
ex
;
}
refreshToken
();
return
function
.
apply
(
getEntity
(
body
));
}
}
catch
(
HttpStatusCodeException
ex
)
{
try
{
Map
<
String
,
String
>
map
=
objectMapper
.
readValue
(
ex
.
getResponseBodyAsString
(),
Map
.
class
);
if
(
map
.
containsKey
(
"error"
))
{
String
error
=
map
.
get
(
"error"
);
if
(
ex
instanceof
HttpClientErrorException
)
{
throw
new
HttpClientErrorException
(
ex
.
getStatusCode
(),
error
);
}
else
if
(
ex
instanceof
HttpServerErrorException
)
{
throw
new
HttpServerErrorException
(
ex
.
getStatusCode
(),
error
);
}
}
}
catch
(
JsonProcessingException
ignore
)
{
}
refreshToken
();
return
function
.
apply
(
getEntity
(
body
));
throw
ex
;
}
}
...
...
This diff is collapsed.
Click to expand it.
gms/src/test/java/it/inaf/ia2/gms/rap/RapClientTest.java
0 → 100644
+
153
−
0
View file @
fd37936e
package
it.inaf.ia2.gms.rap
;
import
it.inaf.ia2.gms.authn.SessionData
;
import
it.inaf.ia2.gms.model.RapUser
;
import
java.nio.charset.StandardCharsets
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpSession
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
static
org
.
mockito
.
ArgumentMatchers
.
any
;
import
static
org
.
mockito
.
ArgumentMatchers
.
anyString
;
import
static
org
.
mockito
.
ArgumentMatchers
.
eq
;
import
org.mockito.Mock
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
org.mockito.junit.MockitoJUnitRunner
;
import
org.springframework.core.ParameterizedTypeReference
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
org.springframework.web.client.HttpClientErrorException
;
import
org.springframework.web.client.HttpClientErrorException.Unauthorized
;
import
org.springframework.web.client.HttpServerErrorException
;
import
org.springframework.web.client.HttpServerErrorException.InternalServerError
;
import
org.springframework.web.client.RestTemplate
;
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
RapClientTest
{
@Mock
private
HttpServletRequest
request
;
@Mock
private
SessionData
sessionData
;
@Mock
private
RestTemplate
restTemplate
;
@Mock
private
RestTemplate
refreshTokenRestTemplate
;
private
RapClient
rapClient
;
@Before
public
void
init
()
{
rapClient
=
new
RapClient
(
restTemplate
);
ReflectionTestUtils
.
setField
(
rapClient
,
"request"
,
request
);
ReflectionTestUtils
.
setField
(
rapClient
,
"refreshTokenRestTemplate"
,
refreshTokenRestTemplate
);
ReflectionTestUtils
.
setField
(
rapClient
,
"scope"
,
"openid"
);
}
@Test
public
void
testUnauthorizedNoRefreshJsonMsg
()
{
String
jsonError
=
"{\"error\":\"Unauthorized: foo\"}"
;
HttpClientErrorException
exception
=
Unauthorized
.
create
(
HttpStatus
.
UNAUTHORIZED
,
"401"
,
HttpHeaders
.
EMPTY
,
jsonError
.
getBytes
(),
StandardCharsets
.
UTF_8
);
when
(
restTemplate
.
exchange
(
anyString
(),
eq
(
HttpMethod
.
GET
),
any
(
HttpEntity
.
class
),
eq
(
new
ParameterizedTypeReference
<
RapUser
>()
{
}))).
thenThrow
(
exception
);
try
{
rapClient
.
getUser
(
"123"
);
}
catch
(
HttpClientErrorException
ex
)
{
assertEquals
(
"401 Unauthorized: foo"
,
ex
.
getMessage
());
}
}
@Test
public
void
testUnauthorizedNoRefreshNotJsonMsg
()
{
String
errorMessage
=
"THIS IS NOT A JSON"
;
HttpClientErrorException
exception
=
Unauthorized
.
create
(
HttpStatus
.
UNAUTHORIZED
,
"401"
,
HttpHeaders
.
EMPTY
,
errorMessage
.
getBytes
(),
StandardCharsets
.
UTF_8
);
when
(
restTemplate
.
exchange
(
anyString
(),
eq
(
HttpMethod
.
GET
),
any
(
HttpEntity
.
class
),
eq
(
new
ParameterizedTypeReference
<
RapUser
>()
{
}))).
thenThrow
(
exception
);
try
{
rapClient
.
getUser
(
"123"
);
}
catch
(
HttpClientErrorException
ex
)
{
assertNotNull
(
ex
.
getMessage
());
}
}
@Test
public
void
testServerErrorJsonMsg
()
{
String
jsonError
=
"{\"error\":\"Fatal error\"}"
;
HttpServerErrorException
exception
=
InternalServerError
.
create
(
HttpStatus
.
INTERNAL_SERVER_ERROR
,
"500"
,
HttpHeaders
.
EMPTY
,
jsonError
.
getBytes
(),
StandardCharsets
.
UTF_8
);
when
(
restTemplate
.
exchange
(
anyString
(),
eq
(
HttpMethod
.
GET
),
any
(
HttpEntity
.
class
),
eq
(
new
ParameterizedTypeReference
<
RapUser
>()
{
}))).
thenThrow
(
exception
);
try
{
rapClient
.
getUser
(
"123"
);
}
catch
(
HttpServerErrorException
ex
)
{
assertEquals
(
"500 Fatal error"
,
ex
.
getMessage
());
}
}
@Test
public
void
testRefreshToken
()
{
when
(
request
.
getSession
(
eq
(
false
))).
thenReturn
(
mock
(
HttpSession
.
class
));
when
(
sessionData
.
getExpiresIn
()).
thenReturn
(-
100
l
);
ReflectionTestUtils
.
setField
(
rapClient
,
"sessionData"
,
sessionData
);
ReflectionTestUtils
.
setField
(
rapClient
,
"clientId"
,
"clientId"
);
ReflectionTestUtils
.
setField
(
rapClient
,
"clientSecret"
,
"clientSecret"
);
ReflectionTestUtils
.
setField
(
rapClient
,
"accessTokenUri"
,
"https://sso.ia2.inaf.it"
);
String
jsonError
=
"{\"error\":\"Unauthorized: token expired\"}"
;
HttpClientErrorException
exception
=
Unauthorized
.
create
(
HttpStatus
.
UNAUTHORIZED
,
"401"
,
HttpHeaders
.
EMPTY
,
jsonError
.
getBytes
(),
StandardCharsets
.
UTF_8
);
when
(
restTemplate
.
exchange
(
anyString
(),
eq
(
HttpMethod
.
GET
),
any
(
HttpEntity
.
class
),
eq
(
new
ParameterizedTypeReference
<
RapUser
>()
{
}))).
thenThrow
(
exception
)
.
thenReturn
(
ResponseEntity
.
ok
(
new
RapUser
()));
ResponseEntity
refreshTokenResponse
=
mock
(
ResponseEntity
.
class
);
Map
<
String
,
Object
>
mockedBody
=
new
HashMap
<>();
mockedBody
.
put
(
"access_token"
,
"<access_token>"
);
mockedBody
.
put
(
"refresh_token"
,
"<refresh_token>"
);
mockedBody
.
put
(
"expires_in"
,
3600
);
when
(
refreshTokenResponse
.
getBody
()).
thenReturn
(
mockedBody
);
when
(
refreshTokenRestTemplate
.
postForEntity
(
anyString
(),
any
(
HttpEntity
.
class
),
any
()))
.
thenReturn
(
refreshTokenResponse
);
RapUser
user
=
rapClient
.
getUser
(
"123"
);
assertNotNull
(
user
);
// verifies that token is refreshed
verify
(
sessionData
,
times
(
1
)).
setAccessToken
(
eq
(
"<access_token>"
));
verify
(
sessionData
,
times
(
1
)).
setExpiresIn
(
eq
(
3600
));
}
}
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