Skip to content

Commit 58b8c03

Browse files
committed
Add possibility to pass request headers to HttpClient
Fixes vojtechhabarta#790 Signed-off-by: Oleksandr Porunov <[email protected]>
1 parent 65d0434 commit 58b8c03

File tree

14 files changed

+273
-102
lines changed

14 files changed

+273
-102
lines changed

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/DefaultRestMethodBuilder.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import cz.habarta.typescript.generator.parser.MethodParameterModel;
44
import cz.habarta.typescript.generator.parser.RestMethodModel;
5-
import cz.habarta.typescript.generator.parser.RestQueryParam;
5+
import cz.habarta.typescript.generator.parser.RestParam;
66
import java.lang.reflect.Method;
77
import java.lang.reflect.Type;
88
import java.util.List;
@@ -12,10 +12,11 @@ public class DefaultRestMethodBuilder implements RestMethodBuilder{
1212
@Override
1313
public RestMethodModel build(Class<?> originClass, String name, Type returnType, Method originalMethod,
1414
Class<?> rootResource, String httpMethod, String path,
15-
List<MethodParameterModel> pathParams, List<RestQueryParam> queryParams,
16-
MethodParameterModel entityParam, List<String> comments) {
15+
List<MethodParameterModel> pathParams, List<RestParam> queryParams,
16+
MethodParameterModel entityParam, List<String> comments, List<RestParam> headers) {
1717

1818
return new RestMethodModel(originClass, name, returnType, originalMethod, rootResource, httpMethod, path,
19-
pathParams, queryParams, entityParam, comments);
19+
pathParams, queryParams, entityParam, comments, headers);
2020
}
21+
2122
}

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/RestMethodBuilder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
import cz.habarta.typescript.generator.parser.MethodParameterModel;
44
import cz.habarta.typescript.generator.parser.RestMethodModel;
5-
import cz.habarta.typescript.generator.parser.RestQueryParam;
5+
import cz.habarta.typescript.generator.parser.RestParam;
66
import java.lang.reflect.Method;
77
import java.lang.reflect.Type;
88
import java.util.List;
99

1010
public interface RestMethodBuilder {
1111

1212
RestMethodModel build(Class<?> originClass, String name, Type returnType, Method originalMethod,
13-
Class<?> rootResource, String httpMethod, String path, List<MethodParameterModel> pathParams, List<RestQueryParam> queryParams, MethodParameterModel entityParam,
14-
List<String> comments);
13+
Class<?> rootResource, String httpMethod, String path, List<MethodParameterModel> pathParams, List<RestParam> queryParams, MethodParameterModel entityParam,
14+
List<String> comments, List<RestParam> headers);
1515

1616
}

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/Settings.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ public class Settings {
110110
public String restResponseType = null;
111111
public String restOptionsType = null;
112112
public boolean restOptionsTypeIsGeneric;
113+
public boolean restHeaderArgumentsParsed;
113114
private List<RestApplicationParser.Factory> restApplicationParserFactories;
114115
public TypeProcessor customTypeProcessor = null;
115116
public RestMethodBuilder customRestMethodBuilder = null;
@@ -776,6 +777,10 @@ public void setRestOptionsType(String restOptionsType) {
776777
}
777778
}
778779

780+
public void setRestHeaderArgumentsParsed(boolean restHeaderArgumentsParsed) {
781+
this.restHeaderArgumentsParsed = restHeaderArgumentsParsed;
782+
}
783+
779784
public List<RestApplicationParser.Factory> getRestApplicationParserFactories() {
780785
if (restApplicationParserFactories == null) {
781786
final List<RestApplicationParser.Factory> factories = new ArrayList<>();

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/compiler/ModelCompiler.java

Lines changed: 61 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
import cz.habarta.typescript.generator.parser.PropertyModel;
5353
import cz.habarta.typescript.generator.parser.RestApplicationModel;
5454
import cz.habarta.typescript.generator.parser.RestMethodModel;
55-
import cz.habarta.typescript.generator.parser.RestQueryParam;
55+
import cz.habarta.typescript.generator.parser.RestParam;
5656
import cz.habarta.typescript.generator.type.JTypeWithNullability;
5757
import cz.habarta.typescript.generator.util.GenericsResolver;
5858
import cz.habarta.typescript.generator.util.Pair;
@@ -622,6 +622,7 @@ private void createRestClients(TsModel tsModel, SymbolTable symbolTable, List<Re
622622
new TsProperty("queryParams", new TsType.OptionalType(TsType.Any)),
623623
new TsProperty("data", new TsType.OptionalType(TsType.Any)),
624624
new TsProperty("copyFn", new TsType.OptionalType(new TsType.FunctionType(Arrays.asList(new TsParameter("data", returnGenericVariable)), returnGenericVariable))),
625+
new TsProperty("headers", new TsType.OptionalType(TsType.Any)),
625626
optionsType != null ? new TsProperty("options", new TsType.OptionalType(optionsType)) : null
626627
))
627628
), new TsType.GenericReferenceType(responseSymbol, returnGenericVariable), null, null)
@@ -728,57 +729,14 @@ private TsMethodModel processRestMethod(TsModel tsModel, SymbolTable symbolTable
728729
parameters.add(processParameter(symbolTable, method, method.getEntityParam()));
729730
}
730731
// query params
731-
final List<RestQueryParam> queryParams = method.getQueryParams();
732-
final TsParameterModel queryParameter;
733-
if (queryParams != null && !queryParams.isEmpty()) {
734-
final List<TsType> types = new ArrayList<>();
735-
if (queryParams.stream().anyMatch(param -> param instanceof RestQueryParam.Map)) {
736-
types.add(new TsType.IndexedArrayType(TsType.String, TsType.Any));
737-
} else {
738-
final List<TsProperty> currentSingles = new ArrayList<>();
739-
final Runnable flushSingles = () -> {
740-
if (!currentSingles.isEmpty()) {
741-
types.add(new TsType.ObjectType(currentSingles));
742-
currentSingles.clear();
743-
}
744-
};
745-
for (RestQueryParam restQueryParam : queryParams) {
746-
if (restQueryParam instanceof RestQueryParam.Single) {
747-
final MethodParameterModel queryParam = ((RestQueryParam.Single) restQueryParam).getQueryParam();
748-
final TsType type = typeFromJava(symbolTable, queryParam.getType(), method.getName(), method.getOriginClass());
749-
currentSingles.add(new TsProperty(queryParam.getName(), restQueryParam.required ? type : new TsType.OptionalType(type)));
750-
}
751-
if (restQueryParam instanceof RestQueryParam.Bean) {
752-
final BeanModel queryBean = ((RestQueryParam.Bean) restQueryParam).getBean();
753-
flushSingles.run();
754-
final Symbol queryParamsSymbol = symbolTable.getSymbol(queryBean.getOrigin(), "QueryParams");
755-
if (tsModel.getBean(queryParamsSymbol) == null) {
756-
tsModel.getBeans().add(new TsBeanModel(
757-
queryBean.getOrigin(),
758-
TsBeanCategory.Data,
759-
/*isClass*/false,
760-
queryParamsSymbol,
761-
/*typeParameters*/null,
762-
/*parent*/null,
763-
/*extendsList*/null,
764-
/*implementsList*/null,
765-
processProperties(symbolTable, null, queryBean),
766-
/*constructor*/null,
767-
/*methods*/null,
768-
/*comments*/null
769-
));
770-
}
771-
types.add(new TsType.ReferenceType(queryParamsSymbol));
772-
}
773-
}
774-
flushSingles.run();
775-
}
776-
boolean allQueryParamsOptional = queryParams.stream().noneMatch(queryParam -> queryParam.required);
777-
TsType.IntersectionType queryParamType = new TsType.IntersectionType(types);
778-
queryParameter = new TsParameterModel("queryParams", allQueryParamsOptional ? new TsType.OptionalType(queryParamType) : queryParamType);
732+
final TsParameterModel queryParameter = convertRestParams(method.getQueryParams(), symbolTable, method, tsModel, "queryParams", "QueryParams");
733+
if(queryParameter != null){
779734
parameters.add(queryParameter);
780-
} else {
781-
queryParameter = null;
735+
}
736+
// body params
737+
final TsParameterModel headersParameter = convertRestParams(method.getHeaders(), symbolTable, method, tsModel, "headers", "Headers");
738+
if(headersParameter != null){
739+
parameters.add(headersParameter);
782740
}
783741
if (optionsType != null) {
784742
final TsParameterModel optionsParameter = new TsParameterModel("options", new TsType.OptionalType(optionsType));
@@ -808,6 +766,7 @@ private TsMethodModel processRestMethod(TsModel tsModel, SymbolTable symbolTable
808766
new TsPropertyDefinition("url", processPathTemplate(pathTemplate)),
809767
queryParameter != null ? new TsPropertyDefinition("queryParams", new TsIdentifierReference("queryParams")) : null,
810768
method.getEntityParam() != null ? new TsPropertyDefinition("data", new TsIdentifierReference(method.getEntityParam().getName())) : null,
769+
headersParameter != null ? new TsPropertyDefinition("headers", new TsIdentifierReference("headers")) : null,
811770
optionsType != null ? new TsPropertyDefinition("options", new TsIdentifierReference("options")) : null
812771
)
813772
)
@@ -820,6 +779,57 @@ private TsMethodModel processRestMethod(TsModel tsModel, SymbolTable symbolTable
820779
return tsMethodModel;
821780
}
822781

782+
private TsParameterModel convertRestParams(List<RestParam> restParams, SymbolTable symbolTable, RestMethodModel method, TsModel tsModel, String parameterName, String beanSuffix){
783+
if (restParams == null || restParams.isEmpty()){
784+
return null;
785+
}
786+
final List<TsType> types = new ArrayList<>();
787+
if (restParams.stream().anyMatch(param -> param instanceof RestParam.Map)) {
788+
types.add(new TsType.IndexedArrayType(TsType.String, TsType.Any));
789+
} else {
790+
final List<TsProperty> currentSingles = new ArrayList<>();
791+
final Runnable flushSingles = () -> {
792+
if (!currentSingles.isEmpty()) {
793+
types.add(new TsType.ObjectType(currentSingles));
794+
currentSingles.clear();
795+
}
796+
};
797+
for (RestParam restParam : restParams) {
798+
if (restParam instanceof RestParam.Single) {
799+
final MethodParameterModel restParamMethodParameterModel = ((RestParam.Single) restParam).getRestParam();
800+
final TsType type = typeFromJava(symbolTable, restParamMethodParameterModel.getType(), method.getName(), method.getOriginClass());
801+
currentSingles.add(new TsProperty(restParamMethodParameterModel.getName(), restParam.required ? type : new TsType.OptionalType(type)));
802+
}
803+
if (restParam instanceof RestParam.Bean) {
804+
final BeanModel paramBean = ((RestParam.Bean) restParam).getBean();
805+
flushSingles.run();
806+
final Symbol paramsSymbol = symbolTable.getSymbol(paramBean.getOrigin(), beanSuffix);
807+
if (tsModel.getBean(paramsSymbol) == null) {
808+
tsModel.getBeans().add(new TsBeanModel(
809+
paramBean.getOrigin(),
810+
TsBeanCategory.Data,
811+
/*isClass*/false,
812+
paramsSymbol,
813+
/*typeParameters*/null,
814+
/*parent*/null,
815+
/*extendsList*/null,
816+
/*implementsList*/null,
817+
processProperties(symbolTable, null, paramBean),
818+
/*constructor*/null,
819+
/*methods*/null,
820+
/*comments*/null
821+
));
822+
}
823+
types.add(new TsType.ReferenceType(paramsSymbol));
824+
}
825+
}
826+
flushSingles.run();
827+
}
828+
boolean allParamsOptional = restParams.stream().noneMatch(param -> param.required);
829+
TsType.IntersectionType paramType = new TsType.IntersectionType(types);
830+
return new TsParameterModel(parameterName, allParamsOptional ? new TsType.OptionalType(paramType) : paramType);
831+
}
832+
823833
private TsParameterModel processParameter(SymbolTable symbolTable, MethodModel method, MethodParameterModel parameter) {
824834
final String parameterName = parameter.getName();
825835
final TsType parameterType = typeFromJava(symbolTable, parameter.getType(), method.getName(), method.getOriginClass());

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/parser/JaxrsApplicationParser.java

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,25 +174,47 @@ private void parseResourceMethod(Result result, ResourceContext context, Class<?
174174
}
175175
}
176176
// query parameters
177-
final List<RestQueryParam> queryParams = new ArrayList<>();
177+
final List<RestParam> queryParams = new ArrayList<>();
178178
for (Parameter param : method.getParameters()) {
179179
final QueryParam queryParamAnnotation = getRsAnnotation(param, QueryParam.class);
180180
if (queryParamAnnotation != null) {
181-
queryParams.add(new RestQueryParam.Single(new MethodParameterModel(queryParamAnnotation.value(), param.getParameterizedType()), false));
181+
queryParams.add(new RestParam.Single(new MethodParameterModel(queryParamAnnotation.value(), param.getParameterizedType()), false));
182182
foundType(result, param.getParameterizedType(), resourceClass, method.getName());
183183
}
184184
final BeanParam beanParamAnnotation = getRsAnnotation(param, BeanParam.class);
185185
if (beanParamAnnotation != null) {
186186
final Class<?> beanParamClass = param.getType();
187187
final BeanModel paramBean = getQueryParameters(beanParamClass);
188188
if (paramBean != null) {
189-
queryParams.add(new RestQueryParam.Bean(paramBean));
189+
queryParams.add(new RestParam.Bean(paramBean));
190190
for (PropertyModel property : paramBean.getProperties()) {
191191
foundType(result, property.getType(), beanParamClass, property.getName());
192192
}
193193
}
194194
}
195195
}
196+
// header parameters
197+
final List<RestParam> headers = new ArrayList<>();
198+
if(settings.restHeaderArgumentsParsed){
199+
for (Parameter param : method.getParameters()) {
200+
final HeaderParam headerParamAnnotation = getRsAnnotation(param, HeaderParam.class);
201+
if (headerParamAnnotation != null) {
202+
headers.add(new RestParam.Single(new MethodParameterModel(headerParamAnnotation.value(), param.getParameterizedType()), false));
203+
foundType(result, param.getParameterizedType(), resourceClass, method.getName());
204+
}
205+
final BeanParam beanParamAnnotation = getRsAnnotation(param, BeanParam.class);
206+
if (beanParamAnnotation != null) {
207+
final Class<?> beanParamClass = param.getType();
208+
final BeanModel paramBean = getHeaderParameters(beanParamClass);
209+
if (paramBean != null) {
210+
headers.add(new RestParam.Bean(paramBean));
211+
for (PropertyModel property : paramBean.getProperties()) {
212+
foundType(result, property.getType(), beanParamClass, property.getName());
213+
}
214+
}
215+
}
216+
}
217+
}
196218
// JAX-RS specification - 3.3.2.1 Entity Parameters
197219
final List<Type> parameterTypes = settings.getTypeParser().getMethodParameterTypes(method);
198220
final List<Pair<Parameter, Type>> parameters = Utils.zip(Arrays.asList(method.getParameters()), parameterTypes);
@@ -234,7 +256,7 @@ private void parseResourceMethod(Result result, ResourceContext context, Class<?
234256
final List<String> comments = Swagger.getOperationComments(swaggerOperation);
235257
// create method
236258
model.getMethods().add(restMethodBuilder.build(resourceClass, method.getName(), resolvedModelReturnType, method,
237-
context.rootResource, httpMethod.value(), context.path, pathParams, queryParams, entityParameter, comments));
259+
context.rootResource, httpMethod.value(), context.path, pathParams, queryParams, entityParameter, comments, headers));
238260
}
239261
// JAX-RS specification - 3.4.1 Sub Resources
240262
if (pathAnnotation != null && httpMethod == null) {
@@ -282,6 +304,36 @@ private static BeanModel getQueryParameters(Class<?> paramBean) {
282304
}
283305
}
284306

307+
private static BeanModel getHeaderParameters(Class<?> paramBean) {
308+
final List<PropertyModel> properties = new ArrayList<>();
309+
final List<Field> fields = Utils.getAllFields(paramBean);
310+
for (Field field : fields) {
311+
final HeaderParam annotation = getRsAnnotation(field, HeaderParam.class);
312+
if (annotation != null) {
313+
properties.add(new PropertyModel(annotation.value(), field.getGenericType(), /*optional*/true, null, field, null, null, null));
314+
}
315+
}
316+
try {
317+
final BeanInfo beanInfo = Introspector.getBeanInfo(paramBean);
318+
for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) {
319+
final Method writeMethod = propertyDescriptor.getWriteMethod();
320+
if (writeMethod != null) {
321+
final HeaderParam annotation = getRsAnnotation(writeMethod, HeaderParam.class);
322+
if (annotation != null) {
323+
properties.add(new PropertyModel(annotation.value(), propertyDescriptor.getPropertyType(), /*optional*/true, null, writeMethod, null, null, null));
324+
}
325+
}
326+
}
327+
} catch (IntrospectionException e) {
328+
TypeScriptGenerator.getLogger().warning(String.format("Cannot introspect '%s' class: " + e.getMessage(), paramBean));
329+
}
330+
if (properties.isEmpty()) {
331+
return null;
332+
} else {
333+
return new BeanModel(paramBean, null, null, null, null, null, properties, null);
334+
}
335+
}
336+
285337
private MethodParameterModel getEntityParameter(Class<?> resourceClass, Method method, List<Pair<Parameter, Type>> parameters) {
286338
for (Pair<Parameter, Type> pair : parameters) {
287339
if (!Utils.hasAnyAnnotation(annotationClass -> pair.getValue1().getAnnotation(annotationClass), Arrays.asList(

0 commit comments

Comments
 (0)