Skip to content
This repository was archived by the owner on Jun 11, 2024. It is now read-only.

Commit ddfb857

Browse files
authored
Swagger codegen (#138)
* tmp * remarks; ruby client test - in progress * Ruby client integration test * Remarks * python client * js client test * Refactoring * Refactoring * build fix * update dependencies * python client fix * Tests fixes
1 parent 7b3c0c8 commit ddfb857

File tree

28 files changed

+1079
-11
lines changed

28 files changed

+1079
-11
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
* Modifications Copyright (c) 2019 BrowserUp, Inc.
3+
*/
4+
5+
plugins {
6+
id 'java-library'
7+
id 'groovy'
8+
id "io.swagger.core.v3.swagger-gradle-plugin" version "2.1.6"
9+
id 'org.openapi.generator' version '4.3.1'
10+
}
11+
12+
ext {
13+
jerseyVersion = '2.32'
14+
}
15+
16+
resolve {
17+
outputFileName = 'openapi'
18+
outputFormat = 'YAML'
19+
prettyPrint = 'TRUE'
20+
openApiFile = file("src/main/resources/openapi-config.json")
21+
classpath = sourceSets.main.runtimeClasspath
22+
readerClass = "com.browserup.bup.rest.openapi.CustomOpenApiReader"
23+
resourcePackages = ['com.browserup.bup.rest.resource']
24+
outputPath = "$buildDir/openapi"
25+
}
26+
27+
class Constants {
28+
static String apiPackage = 'browserup'
29+
static String modelPackage = 'browserup.model'
30+
}
31+
32+
/*
33+
https://github.com/OpenAPITools/openapi-generator/issues/3285
34+
*/
35+
class PythonClientPostProcessor {
36+
String projectDir
37+
38+
void process() {
39+
def clientDir = new File("$projectDir/build/openapi-clients/python")
40+
clientDir.eachFileRecurse {
41+
if (it.name.endsWith(".py")) {
42+
processInitFile(it)
43+
}
44+
}
45+
new File("${clientDir}/openapi_client/${Constants.apiPackage}/model/__init__.py") <<
46+
new File("${clientDir}/openapi_client/${Constants.modelPackage}/__init__.py").text
47+
}
48+
49+
private static void processInitFile(File initFile) {
50+
initFile.text = initFile.text.replaceAll(
51+
~/(from ${Constants.apiPackage}.default_api import)/,
52+
"from openapi_client.${Constants.apiPackage}.default_api import"
53+
)
54+
}
55+
}
56+
57+
class ClientInfo {
58+
String language
59+
Closure postProcessor
60+
}
61+
62+
def clients = [
63+
new ClientInfo(language: 'JavaScript'),
64+
new ClientInfo(language: 'Ruby'),
65+
new ClientInfo(
66+
language: 'Python',
67+
postProcessor: new PythonClientPostProcessor(projectDir: projectDir).&process)
68+
] as ClientInfo[]
69+
70+
clients.each { client ->
71+
def lang = client.language
72+
def postProcessor = client.postProcessor
73+
74+
task "openApiGenerate${lang}Client"(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
75+
def language = lang.toLowerCase()
76+
generatorName = language
77+
inputSpec = "$buildDir/openapi/openapi.yaml".toString()
78+
outputDir = "$buildDir/openapi-clients/$language/".toString()
79+
apiPackage = Constants.apiPackage
80+
modelPackage = Constants.modelPackage
81+
invokerPackage = "browserup.invoker"
82+
systemProperties = [
83+
modelDocs: 'false'
84+
]
85+
skipValidateSpec = true
86+
logToStderr = true
87+
generateAliasAsModel = false
88+
}
89+
if (postProcessor) tasks.getByName("openApiGenerate${lang}Client").doLast(postProcessor)
90+
}
91+
92+
test {
93+
testLogging.showStandardStreams = true
94+
}
95+
96+
task openApiGenerateClients(dependsOn: resolve) {
97+
clients.each { c ->
98+
dependsOn "openApiGenerate${c.language}Client"
99+
}
100+
101+
doLast {
102+
clients.each { client ->
103+
def langName = client.language.toLowerCase()
104+
delete "src/test/${langName}/client"
105+
copy {
106+
from "$buildDir/openapi-clients/${langName}/"
107+
into "src/test/${langName}/client"
108+
}
109+
}
110+
111+
project.delete "$buildDir/openapi-clients"
112+
}
113+
}
114+
115+
archivesBaseName = 'browserup-proxy-rest-clients'
116+
117+
dependencies {
118+
implementation project(':browserup-proxy-core')
119+
implementation project(':browserup-proxy-rest')
120+
121+
testImplementation "org.glassfish.jersey.containers:jersey-container-servlet-core:${jerseyVersion}"
122+
testImplementation "org.glassfish.jersey.media:jersey-media-json-jackson:${jerseyVersion}"
123+
testImplementation "org.glassfish.jersey.inject:jersey-hk2:${jerseyVersion}"
124+
testImplementation "org.glassfish.jersey.ext:jersey-bean-validation:${jerseyVersion}"
125+
126+
testImplementation project(':browserup-proxy-mitm')
127+
128+
testImplementation "com.google.inject:guice:$guiceVersion"
129+
testImplementation "com.google.inject.extensions:guice-servlet:$guiceVersion"
130+
testImplementation "com.google.inject.extensions:guice-multibindings:$guiceVersion"
131+
132+
testImplementation 'com.google.sitebricks:sitebricks:0.8.11'
133+
134+
testImplementation 'junit:junit:4.12'
135+
testImplementation "org.apache.logging.log4j:log4j-api:${log4jVersion}"
136+
testImplementation "org.apache.logging.log4j:log4j-core:${log4jVersion}"
137+
testImplementation "org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}"
138+
testImplementation 'org.codehaus.groovy:groovy-all:2.5.7'
139+
testImplementation 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.2'
140+
testImplementation 'org.hamcrest:hamcrest:2.1'
141+
testImplementation 'org.hamcrest:hamcrest-library:2.1'
142+
testImplementation 'org.mockito:mockito-core:3.0.0'
143+
testImplementation 'org.seleniumhq.selenium:selenium-api:3.4.0'
144+
testImplementation 'org.awaitility:awaitility:3.1.6'
145+
testImplementation 'xyz.rogfam:littleproxy:2.0.0-beta-3'
146+
testImplementation 'com.github.tomakehurst:wiremock-jre8:2.24.0'
147+
testImplementation 'org.testcontainers:testcontainers:1.12.0'
148+
}
149+
150+
openApiGenerateClients.mustRunAfter(resolve)
151+
152+
test.dependsOn(openApiGenerateClients)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"resourcePackages" : [
3+
"com.browserup.bup.rest.resource"
4+
],
5+
"openapi" : "3.0.1",
6+
"info": {
7+
"version": "1.0",
8+
"title": "BrowserUp Proxy API",
9+
"description": "BrowserUp Proxy API",
10+
"contact": {
11+
"email": "hello@browserup.com"
12+
},
13+
"license": {
14+
"name": "Apache 2.0",
15+
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
16+
}
17+
}
18+
}
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/*
2+
* Modifications Copyright (c) 2019 BrowserUp, Inc.
3+
*/
4+
5+
package com.browserup.bup
6+
7+
/*
8+
* Modifications Copyright (c) 2019 BrowserUp, Inc.
9+
*/
10+
11+
import com.browserup.bup.MitmProxyServer
12+
import com.browserup.bup.proxy.MitmProxyManager
13+
import com.browserup.bup.proxy.bricks.ProxyResource
14+
import com.browserup.bup.proxy.guice.ConfigModule
15+
import com.browserup.bup.proxy.guice.JettyModule
16+
import com.browserup.bup.util.BrowserUpProxyUtil
17+
import com.github.tomakehurst.wiremock.junit.WireMockRule
18+
import com.google.inject.Guice
19+
import com.google.inject.Injector
20+
import com.google.inject.servlet.GuiceServletContextListener
21+
import com.google.sitebricks.SitebricksModule
22+
import groovyx.net.http.HTTPBuilder
23+
import groovyx.net.http.Method
24+
import org.apache.http.entity.ContentType
25+
import org.awaitility.Awaitility
26+
import org.eclipse.jetty.server.Server
27+
import org.eclipse.jetty.servlet.ServletContextHandler
28+
import org.junit.After
29+
import org.junit.Before
30+
import org.junit.Rule
31+
import org.slf4j.Logger
32+
import org.slf4j.LoggerFactory
33+
34+
import javax.servlet.ServletContextEvent
35+
import java.util.concurrent.TimeUnit
36+
37+
import static com.github.tomakehurst.wiremock.client.WireMock.*
38+
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options
39+
import static org.junit.Assert.assertEquals
40+
41+
abstract class WithRunningProxyRestTest {
42+
private static final Logger LOG = LoggerFactory.getLogger(MitmProxyManager)
43+
44+
protected MitmProxyManager proxyManager
45+
protected MitmProxyServer proxy
46+
protected Server restServer
47+
48+
protected String[] getArgs() {
49+
['--port', '0'] as String[]
50+
}
51+
52+
abstract String getUrlPath();
53+
54+
String getFullUrlPath() {
55+
return "/proxy/${proxy.port}/${urlPath}"
56+
}
57+
58+
protected int mockServerPort
59+
protected int mockServerHttpsPort
60+
61+
@Rule
62+
public WireMockRule wireMockRule = new WireMockRule(options().port(0).httpsPort(0))
63+
64+
@Before
65+
void setUp() throws Exception {
66+
Injector injector = Guice.createInjector(new ConfigModule(args), new JettyModule(), new SitebricksModule() {
67+
@Override
68+
protected void configureSitebricks() {
69+
scan(ProxyResource.class.getPackage())
70+
}
71+
})
72+
73+
proxyManager = injector.getInstance(MitmProxyManager)
74+
75+
LOG.debug("Starting BrowserUp Proxy version " + BrowserUpProxyUtil.versionString)
76+
77+
new Thread(new Runnable() {
78+
@Override
79+
void run() {
80+
startRestServer(injector)
81+
}
82+
}).start()
83+
84+
LOG.debug("Waiting till BrowserUp Rest server is started")
85+
86+
Awaitility.await().atMost(10, TimeUnit.SECONDS).until({ -> restServer != null && restServer.isStarted() })
87+
88+
LOG.debug("BrowserUp Rest server is started successfully")
89+
90+
LOG.debug("Waiting till BrowserUp Proxy server is started")
91+
92+
proxy = proxyManager.create(0)
93+
94+
Awaitility.await().atMost(5, TimeUnit.SECONDS).until({ -> proxyManager.get().size() > 0 })
95+
96+
LOG.debug("BrowserUp Proxy server is started successfully")
97+
98+
mockServerPort = wireMockRule.port();
99+
mockServerHttpsPort = wireMockRule.httpsPort();
100+
101+
waitForProxyServer()
102+
}
103+
104+
def waitForProxyServer() {
105+
Awaitility.await().atMost(5, TimeUnit.SECONDS).until({ ->
106+
def successful = false
107+
proxyRestServerClient.request(Method.GET, ContentType.TEXT_PLAIN) { req ->
108+
uri.path = "/proxy"
109+
response.success = { _, reader ->
110+
successful = true
111+
}
112+
response.failure = { _, reader ->
113+
successful = false
114+
}
115+
}
116+
return successful
117+
})
118+
}
119+
120+
HTTPBuilder getTargetServerClient() {
121+
def http = new HTTPBuilder("http://localhost:${mockServerPort}")
122+
http.setProxy('localhost', proxy.port, 'http')
123+
http
124+
}
125+
126+
HTTPBuilder getProxyRestServerClient() {
127+
new HTTPBuilder("http://localhost:${restServer.connectors[0].localPort}")
128+
}
129+
130+
def sendGetToProxyServer(Closure configClosure) {
131+
proxyRestServerClient.request(Method.GET, ContentType.WILDCARD, configClosure)
132+
}
133+
134+
void requestToTargetServer(url, expectedResponse) {
135+
targetServerClient.request(Method.GET, ContentType.TEXT_PLAIN) { req ->
136+
uri.path = "/${url}"
137+
response.success = { _, reader ->
138+
assertEquals(expectedResponse, reader.text)
139+
}
140+
response.failure = { _, reader ->
141+
assertEquals(expectedResponse, reader.text)
142+
}
143+
}
144+
}
145+
146+
@After
147+
void tearDown() throws Exception {
148+
LOG.debug('Stopping proxy servers')
149+
for (def proxyServer : proxyManager.get()) {
150+
try {
151+
proxyManager.delete(proxyServer.port)
152+
} catch (Exception ex) {
153+
LOG.error('Error while stopping proxy servers', ex)
154+
}
155+
}
156+
157+
if (restServer != null) {
158+
LOG.debug('Stopping rest proxy server')
159+
try {
160+
restServer.stop()
161+
} catch (Exception ex) {
162+
LOG.error('Error while stopping rest proxy server', ex)
163+
}
164+
}
165+
}
166+
167+
private void startRestServer(Injector injector) {
168+
restServer = injector.getInstance(Server.class)
169+
def contextListener = new GuiceServletContextListener() {
170+
@Override
171+
protected Injector getInjector() {
172+
return injector
173+
}
174+
}
175+
restServer.start()
176+
contextListener.contextInitialized(
177+
new ServletContextEvent((restServer.handler as ServletContextHandler).servletContext))
178+
try {
179+
restServer.join()
180+
} catch (InterruptedException ignored) {
181+
Thread.currentThread().interrupt()
182+
}
183+
}
184+
185+
protected void mockTargetServerResponse(String url, String responseBody, int delayMilliseconds=0) {
186+
def response = aResponse().withStatus(200)
187+
.withBody(responseBody)
188+
.withHeader('Content-Type', 'text/plain')
189+
.withFixedDelay(delayMilliseconds)
190+
stubFor(get(urlEqualTo("/${url}")).willReturn(response))
191+
}
192+
}

0 commit comments

Comments
 (0)